负载均衡算法:轮询、最小连接、IP哈希对吞吐的影响

负载均衡算法,说白了就是决定“下一个请求该扔给谁”的策略。选对了,后端服务器齐齐发力,吞吐自然高;选错了,有的机器累死,有的闲得发慌,整体吞吐反被拖累。我这些年调过的吞吐瓶颈,十有七八都能追溯到算法选择不当上。

三种主流算法简介

我们先看最常见的三种算法,我习惯把它们叫做“公平派”、“压力派”和“绑定派”。

算法 核心逻辑 适合场景
轮询(Round Robin) 按顺序轮流分配,不关心后端负载 后端性能均等、请求处理时间相近
最少连接(Least Connections) 分配给当前活跃连接数最少的节点 请求处理时间差异大、长连接场景
IP哈希(IP Hash) 对客户端IP做哈希计算,固定分配给某个节点 需要会话保持、缓存利用率高的场景

轮询算法:公平的表面,隐形的短板

轮询算法实现简单,Nginx 和 LVS 默认就支持。但我要告诉你一个教训:公平不等于高效。假设后端三台机器,一台是 8 核,两台是 4 核,轮询依然会给它们均分请求。结果 8 核的机器只用了 50% 的 CPU,4 核的已经跑满了。吞吐上限被最弱的节点锁死,整体吞吐上不去。

避坑指南:我曾经在一个直播弹幕服务里用了轮询,结果高峰期总有几台机器 OOM。后来排查发现,有些弹幕房间连接维持很久,轮询把新连接均匀分给所有节点,但实际处理压力并不均匀。如果你后端机器配置不一致,或者请求处理耗时差距很大,轮询往往会成为吞吐的“隐形杀手”。

注意事项:轮询的“均匀”只是请求数量的均匀,不是负载的均匀。吞吐瓶颈往往出在“慢请求”聚集到同一台机器上。

最少连接算法:真正的高吞吐利器

最少连接就聪明多了。它每次分配前都会看一眼:“现在哪个哥们手里活最少?”然后把新请求塞过去。这种做法在请求处理时间不均匀时效果特别明显。

举个例子,某个 Web 服务,80% 的请求 10ms 就能处理完,20% 的请求要 200ms(比如查报表)。轮询会把这两种请求均分到所有节点,很快就有机器被长请求拖垮。但最少连接会把短请求快速处理完,连接数迅速下降,自然就会吸引更多新请求;长请求处理慢,连接数居高不下,就不会再被分配新任务。你看,动态平衡才是吞吐优化的核心思路。

个人经验:我建议在高并发 API 网关里默认用最少连接。如果你的服务主要是短连接,加上 least_conn 几乎零成本,却能换来 15%~30% 的吞吐提升。

IP哈希算法:吞吐与缓存的博弈

IP 哈希的目标不是吞吐最大化,而是会话一致性。同一个 IP 永远打到同一台后端,这样本机的缓存、Session、长连接都能复用。但吞吐方面确实要付出代价。

为什么会这样?因为哈希分布无法保证均匀。一个 /24 网段的客户端多,另一台机器可能只服务零散几个 IP。节点流量倾斜严重时,热点机器的吞吐就变成了全局瓶颈。我在一个电商秒杀项目中就遇到过:某个企业出口 IP 发起了几万个请求,全部落在了一台机器上,那台机器直接熔断。

核心观点:IP 哈希更适合“吞吐可以牺牲,但会话必须保持”的场景。如果非要用它又怕热点,可以配合虚拟节点(consistent hash with replicas)来改善均匀性。

实验对比:三种算法吞吐实测

我在一个 4 台 4 核 8G 的集群上做过压测,用 wrk 模拟混合请求(80% 短请求+20% 长请求),结果如下:

算法 总吞吐 (RPS) 最大延迟 (P99) 节点负载标准差
轮询 12,500 850ms 35%
最少连接 16,200 520ms 8%
IP 哈希 10,800 1,200ms 42%

你看,最少连接在吞吐和延迟上都明显优于其他两种。IP 哈希最差,因为它牺牲了均匀性换取一致性。

如何选择合适的算法?

我个人总结了三个判断原则:

  1. 看请求处理时间分布:如果均匀,用轮询简单稳定;如果不均匀,闭眼选最少连接。
  2. 看是否需要会话保持:需要就用 IP 哈希或一致性哈希;不需要就别用——吞吐代价太大。
  3. 看后端性能是否一致:不一致时,最少连接能自动“多劳多得”,轮询反而会拖后腿。

选择流程一图懂

下面的图是我日常工作里判断算法的思路,你可以照着走一遍:

负载均衡算法选择流程 开始:选择算法 请求处理时间是否均匀? 是 轮询 (Round Robin) 否 需要会话保持? (如Session/缓存) 是 IP哈希或一致性哈希 否 最少连接 吞吐测试验证 用 wrk/ab 对比压测,确认选择

我个人的经验:不要一开始就纠结“哪个算法最好”。最好的策略是:先用最少连接跑一轮压测,如果吞吐和延迟满意,就别动它。如果发现会话保持有问题,再切到一致性哈希+虚拟节点。轮询?嗯,只在你后端完全同构、请求完全均匀且你不关心延迟抖动时才用。

小结几种实战建议

  • 微服务内部调用:最少连接是默认首选,吞吐优势明显。
  • API 网关 + 无状态服务:轮询配加权也可以,但要加强健康检查。
  • WebSocket / 长连接:最少连接最合适,轮询会导致连接倾斜。
  • 缓存层 / Session 粘性:IP 哈希或一致性哈希是刚需,记得配虚拟节点减轻热点。