知识卡片

负载最低优先与性能最优类:靠感知服务器状态换取分配精度,但代价高昂

结构图卡

内容

[[负载均衡算法四大类,及轮询/加权轮询的双刃剑特性]]完全不感知服务器运行时状态,负载最低优先和性能最优类算法正是为了弥补这个缺陷而生,但代价都是复杂度大幅上升。负载最低优先把任务分配给当前负载最低的服务器,”负载”的衡量指标要按场景选(LVS这类4层设备常用连接数、Nginx这类7层系统需要扩展才能支持HTTP请求数、自研系统则按业务特点选CPU负载或I/O负载);但落地起来复杂度很高——最少连接数优先算法要求负载均衡系统持续统计每台服务器当前建立的连接数,且只适用于”每个连接请求都会转发给服务器处理”的场景,如果负载均衡系统和服务器之间是固定连接池方式(比如通过连接池连MySQL集群),就不适合用这种算法;CPU负载最低优先算法要求持续收集每台服务器的CPU负载,还要决定用1分钟还是15分钟的负载值作为判断标准——不存在哪个时间窗口绝对更好,窗口太短容易频繁波动、太长又可能在峰值来临时响应迟钝,不同业务的最优窗口不一样。用一个直观的对比来说:轮询可能5行代码就能实现,负载最低优先可能要上千行,甚至需要负载均衡系统和后端服务器两边都配合开发,一旦设计不当或不适配业务特点,这套复杂算法本身反而可能变成新的性能瓶颈——这也是为什么负载最低优先看起来效果最好,实际应用场景反而没有轮询和加权轮询普遍的原因。性能最优类站在客户端视角,优先把任务分给响应最快的服务器,本质上和负载最低优先一样是在感知服务器状态,只是换了个外部指标(响应时间)来衡量,因此也背负着类似的复杂度:一是要收集统计每台服务器每个任务的响应时间,任务量大时这个统计动作本身就会消耗不少性能;二是为了减轻统计开销可以改用采样,但采样率本身又是个难题——太低不准、太高依然耗性能;三是无论全量统计还是采样统计,都要选一个合适的统计周期(10秒最优、1分钟最优还是5分钟最优),没有放之四海而皆准的答案,往往需要系统上线后不断调优才能找到适合的设置。

结构图

flowchart TB
  A["感知服务器状态类算法:换取更优分配,代价是复杂度大增"]
  A --> B["负载最低优先<br/>按连接数/CPU负载/I-O负载分配"]
  B --> B1["最少连接数优先:仅适用于每次请求都转发的场景<br/>连接池方式不适用"]
  B --> B2["CPU负载最低优先:需选1分钟还是15分钟窗口<br/>太短波动大,太长响应迟钝"]
  B1 --> B3["实现复杂度:轮询约5行代码<br/>负载最低优先可能要上千行+双端开发"]
  B2 --> B3
  A --> C["性能最优类<br/>按响应时间分配,客户端视角"]
  C --> C1["全量统计响应时间→消耗性能"]
  C --> C2["改用采样统计→采样率难定(太低不准/太高耗性能)"]
  C --> C3["无论全量或采样,都要选合适统计周期<br/>无普适答案,常需上线后持续调优"]
  B3 --> D["共同结论:设计不当反而可能自己成为新瓶颈<br/>实际应用远没有轮询普及"]
  C3 --> D

参考来源

- 位置:《从零开始学架构》第21讲《高性能负载均衡:算法》"负载最低优先""性能最优类"(源文件:_epub-src/OEBPS/text00002.html) - 结论依据:原文说明"最少连接数优先的算法……其应用场景仅限于负载均衡接收的任何连接请求都会转发给服务器进行处理,否则……就不适合采取这种算法","CPU 负载最低优先的算法……要确定是以 1 分钟的负载为标准,还是以 15 分钟的负载为标准,不存在 1 分钟肯定比 15 分钟要好或者差",以及性能最优类"采样率太低会导致结果不准确,采样率太高会导致性能消耗较大……需要选择合适的周期……没有放之四海而皆准的周期",直接支撑本卡片结论与结构图。 - 原始内容:负载最低优先算法基本上能够比较完美地解决轮询算法的缺点……通俗来讲,轮询可能是 5 行代码就能实现的算法,而负载最低优先算法可能要 1000 行才能实现……性能最优优先类算法存在的问题和负载最低优先类算法类似,复杂度都很高。