Obsidian同步到博客
cp 'C:\Users\10785\Documents\obsidian\drivehq\drivehq\知识\图书馆\周志明的软件架构课\周志明的软件架构课笔记.md' C:\Users\10785\code\andywu1998.github.io\_posts\2024-05-22-周志明的软件架构课.md
20| 常见的四层负载均衡的工作模式是怎样的
提到了什么名词
- 负载均衡
- 四层负载均衡
- 七层负载均衡
- 数据链路层负载均衡
- 虚拟IP地址
- 网络层负载均衡
- IP隧道模式
- 应用层负载均衡
- 均衡策略
- 轮询均衡
- 权重轮询均衡
- 随机均衡
- 权重随机均衡
- 一致性hash均衡
- 响应速度均衡
- 最小连接均衡
名词解释
负载均衡
个人理解,是为了让网络请求能够分散到不同的服务器处理,分为四层负载均衡和七层负载均衡。
七层
- 应用层
- 表达层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
四层负载均衡
四层负载均衡指的是都维持同一个TCP连接,而不是它只工作在第四层。其实主要工作在数据链路层和网络层。所以就有数据链路层负载均衡和网络层负载均衡两种四层负载均衡。
数据链路层负载均衡
数据链路层传输的内容是数据帧,用来表示地址的是MAC源地址,MAC目标地址。
四层负载均衡做的事情就是修改MAC目标地址,让用户原本是发给负载均衡器的数据帧被二层交换机转发到服务器中。
Virtual IP Adress VIP
在使用数据链路层负载均衡的时候,需要把服务器的虚拟IP地址改成和负载均衡器的虚拟IP一样。
数据链路层负载均衡的响应工作模式
因为源地址没有被改变,所以服务器可以直接把相应发给客户端,不需要经过负载均衡器。
所以请求的链路是:客户端->负载均衡器->实际服务器->客户端
数据链路层负载均衡的局限
因为它只能改MAC地址交给第二层交换机去转发到目的服务器,所以它只能工作在同一个子网中,必须是二层可达的。
网络层负载均衡
网络层是表示源和目的的是源IP地址和目的IP地址
网络层负载均衡的两种修改方式 隧道(套娃)模式
套娃模式,就是保持原来的IP数据包不变,给它包一层,原来的一整个包就是新包的payload,然后新包的目的地址是真实服务器地址。真实服务器拿到包之后先把外层的包拆掉。因为原来的数据包的源地址还是客户端的地址,所以这种模式仍然可以不经过负载均衡器就直接相应客户端。
缺点:
- 服务器必须会拆包,不过几乎所有linux都支持这种模式。
- 真实服务器必须有和负载均衡器相同的虚拟IP地址。
网络层负载均衡模式之 NAT模式
负载均衡器直接把真实数据包的目的地址改掉,改成实际的服务器地址。
这样会产生一个问题,就是服务器的地址和负载均衡器的地址不是同一个地址,所以服务器不能直接响应客户端,因为客户端本来发送的目的地址是负载均衡器的地址,如果它收到源地址是实际服务器的地址的话它会不认识。所以就需要实际服务器把相应再次发给负载均衡器,负载均衡器把源地址改成负载均衡器自己的地址。这样才能保证客户端认识真实服务器发出去的数据包。
缺点,因为相应和要回到负载均衡器,所以会有较大的性能损耗。
- 还有一种更彻底的NAT模式叫Source NAT就是负载均衡器不但把目标地址改了,也把源地址改成自己的。这样的好处是网关都不用配置了,能让流量正常的经过三层路由,回到负载均衡上。这样的是真的透明的。
- 缺点:真实服务器拿不到真实的客户端地址,有一些需要根据IP做的业务逻辑就不能做了。
应用层负载均衡
四层负载均衡就像是一个自动排号机,每个到达的客户都能被指定到相应窗口。七层负载均衡像是大堂经理,确认客户要办的业务,然后根据内部资源同样协调客户到哪个窗口,并且如果有一些很简单的业务,大堂经理直接解决了。
优点
- 静态资源缓存
- 协议升级
- 安全防护
- 访问控制
- 更智能的实现:比如根据用户身份路由,导流到贵宾服务器。
均衡策略
轮询
简单轮流
权重轮询
按照权重来轮询
随机
权重随机
有一定权重的随机
一致性hash均衡
用MAC IP地址或者更上层的东西计算hash,计算请求应该落到哪些节点上。
相应速度均衡
最少链接数均衡
适合长时间处理的业务,比如FTP业务。
21- 服务端缓存的三种属性
提到的名词
- 缓存
- 缓存属性
- 吞吐量
- 命中率
- 拓展功能
- 分布式支持
- 命中率和淘汰策略
- FIFO
- LRU
- LFU
- Tiny LFU
- W-TinyLFU
- 加载器
- 淘汰策略
- 失效策略
- 事件通知
- 并发级别
- 容量控制
- 引用方式
- 统计信息
- 持久化
名词解释
缓存属性
- 吞吐量
- 命中率
- 拓展功能
- 分布式支持 本讲讲前三种属性。
吞吐量
- 线程安全会带来一定的吞吐量损失。
- 主流方案:Caffeine,ConcurrentLinkedHashMap,LinkedHashMap, Guava Cache, Ehcache, Infinispan Embedded
- 避免数据竞争,Caffeine用环形缓冲区来避免数据竞争。将原来写在map上的锁转移到日志追加上。
命中率和淘汰策略
- 缓存有时候不会命中,所以有命中率。
- FIFO:先进先出的淘汰策略,会很大幅度降低命中率。因为越早进入的往往越经常被访问。
- LRU:优先淘汰最久未被访问的数据。但如果有一些数据经常被访问,只是最近因为某种原因没被访问,仍然面临被淘汰的命运,所以LRU仍然可能淘汰高价值的数据。
- LFU:优先淘汰最不经常使用的数据,给每个数据添加访问计数器,每访问一次就加一
- 需要维护一个计数器,开销昂贵,会影响吞吐量。
- 如果某一个数据曾经经常被访问,但现在不需要了,也很难清除缓存。
- TinyLFU:采用Sketch结构,借用Count-Min Sketch算法可以用相对小得多得空间来记录频率和空间。
- 采用了基于基于滑动窗口的热度衰减算法。
- W-TinyLFU:TinyLFU实现减少计数器维护频率的同事,也无法很好解决稀疏突发访问问题。
- 系数突发访问是一些绝对频率较小,但突发访问频率很高的数据。
- 整体LFU,局部LRU。
- 把新记录放到Window Cache的LRU缓存前面。让这些对象在Window Cache里积累热度,如果能通过Tiny LFU的过滤器,再进入MainCache里。
- Main Cache根据访问频繁程度分为不同的段,从某一个段局部来看是LRU的,当一个段满了就淘汰到后一段去存储。知道最后一段也满了就彻底清楚缓存。
22 分布式缓存如何与本地缓存配合,提高系统性能
提到了哪些名词
- 分布式缓存
- 复制式缓存
- 集中式缓存
- 透明多级缓存
- 缓存穿透
- 缓存击穿
- 缓存雪崩
- 缓存污染
复制式缓存
- 每个节点都有自己的内存缓存,同时还有一个分布式缓存。
- 内存缓存的数据来源于从分布式缓存的复制。
集中式缓存
- 需要网络访问
- 独立的进程空间,这样能够多语言一起用一个缓存。
透明多级缓存
- 相关的JDK把缓存分层,先查进程内缓存,查不到去查分布式缓存(redis),再查不到去查真正数据源。
- 从数据源回填到分布式缓存
- 从分布式缓存回填到进程内缓存。
缓存穿透
- 访问数据库里本来就没有的数据,这样每次请求都会打到数据库。
- 一定时间内缓存空值。
- 用布隆过滤器来过滤数据库里肯定不存在的值。
缓存击穿
- 热点数据失效了,并发请求都到达真实数据源。
- 解决方法:加锁,只有一个请求可以流入真实数据源。如果是分布式缓存问题,就分布式锁。
缓存雪崩
- 相比于缓存击穿是针对单个热点数据,而缓存雪崩是大批量热点数据失效。这可能是因为批量预热导致的。
- 分布式缓存集群。
- 启用透明多级缓存。
- 随机过期时间。
缓存污染
- Cache Aside模式
- 简单说就是读的时候先读缓存,没读到再读数据源。
- 写数据直接写数据源,然后失效而不是更新缓存。
- 有一个风险,如果一个数据一开始没有缓存的,在读数据源之后,回填缓存之前,数据源的数据更新了,这个时候就会造成缓存和数据源不一致。但是这个概率非常低。
- 如果这个概率也想避免的话可以用paxos算法。
23 认证:系统如何正确分辨操作用户的真实身份?
提到哪些名词
- 认证
- 授权
- 凭证
- 保密
- 传输
- 验证
认证
- 基于通讯信道上的认证
- 建立连接之前,先证明你是谁。典型是SSL/TLS
- 通讯协议上的认证
- http协议认证
- 通讯内容认证
- web内容认证。
http认证
http认证框架
- 客户端访问需要鉴权的资源。
- 服务端返回Unauthorized(401)
- 客户端认证
- 带着认证访问资源
- 服务端认证。
多种方案:
- Digest
- Bearer
- HOBA
基于通讯内容:web认证
一个开放标准:WebAuthn
WebAuthn彻底抛弃传统的密码登录方式,采用生物识别或者实体密钥来作为身份验证。主要分为注册和登录两部分。
注册部分
- 用户进入系统注册界面填的信息不属于标准范围。
- 用户点击提交注册信息的时候,服务端暂存用户提交的数据,返回一个随机字符串(challenge)和用户的UserID
- 客户端的webAuthn API收到challenge和UserID,把这些信息发送给验证器,验证器可以是Touch Bar或者Face ID
- 验证器提示用户验证,验证结果是一对公钥和私钥,验证器存好密钥,用户信息和域名。用私钥对challenge签名。把签名结果 userID 和公钥返回给客户端。
- 客户端返回给服务器
- 服务器检查UserID是否一致,用公钥来解密签名结果判断和challenge是否一致。
- 一致的话,服务器存储对应的公钥。
登录部分
- 用户点击登录按钮
- 服务器返回随机字符串Challenge和UserID
- 浏览器讲Challenge 和 UserID转发给验证器
- 验证器在注册阶段已经存储了域名的私钥和用户信息,如果域名和用户都相同的话,就不需要生成新的密钥对了。用私钥加密Challenge返回给浏览器。
- 服务端用注册时存储的公钥来解密,如果解密成功并且和发的challenge一样则表示登录成功。