负载均衡算法详解
这章咱们聊聊负载均衡的核心——算法。说白了,就是流量来了到底发给谁的问题。我刚开始做DLP接口高可用时,就栽在了算法选择上。有一次线上压测,轮询配了默认参数,结果两个节点负载差了三倍,差点把一台撑爆。从那以后,我养成了一个习惯:先弄清楚每种算法的脾气,再动手配置。
轮询(Round Robin)
最简单的算法。请求挨个分发给后端服务器,一人一个,循环复始。像极了小学排座位,按顺序来,谁也不多拿。
优点:实现简单,无状态,CPU开销几乎为0。
缺点:strong>服务器性能不一致时,弱的更容易被拖垮。我遇到过一台老机器混在集群里,轮询让它接了一半流量,结果CPU直接飙到90%。
适用场景:后端服务器规格相同、处理能力接近的环境。比如DLP里面的日志采集节点,硬件统一,流量平稳,轮询就够用。
加权轮询(Weighted Round Robin)
给每台服务器配个权重。比如新买的机器权重设3,老旧机器设1,新机器一次扛三个请求,老机器扛一个。说白了就是「能者多劳」。
这里有个坑:权重不要设太大。我曾经见过同事把一台新机器权重开到10,其他机器都是1,结果新机器瞬间被压到极限,其他机器却闲着。加权轮询是概率分配,不是精确按比例,并发高的时候偏差会明显。
最小连接(Least Connections)
每次发请求前,看看哪台服务器当前活跃连接数最少,就发给谁。这是我最常用的一种。为什么呢?因为后端处理时间可能不一样。有的请求简单(查个缓存),有的要查数据库(耗时久)。最小连接能自动把长尾请求分摊开。
不过注意了:最小连接只看「连接数」,不看CPU、内存。有一次我这边DLP接口的某个节点虽然连接数少,但正在跑离线分析任务,CPU已经80%了,最小连接还是把新请求塞给它。结果响应时间直接翻倍。所以,最小连接更适合「连接处理时间」差异大的场景,但不能完全依赖负载均衡器本身的监控。
IP Hash
根据客户端的源IP算哈希,把同一个IP的请求始终发给同一台后端服务器。这个对会话保持特别有用。DLP里面很多接口要求用户登录后所有操作都在同一台节点上(比如会话缓存存在本地),用IP Hash就省去了共享Session的麻烦。
但有个大坑:如果后端节点挂了,哈希重算,原来属于该节点的IP全都要迁移到其他节点。我经历过一次,某台节点宕机后,大量会话突然失效,用户全部踢下线,那叫一个惨。后来我改成「一致性哈希」配合虚拟节点,才把影响范围缩小到原来的1/10。
算法对比一览
| 算法 | 核心逻辑 | 适合场景 | 不适用场景 |
|---|---|---|---|
| 轮询 | 顺序分配 | 服务器规格相同,流量均匀 | 服务器性能差异大 |
| 加权轮询 | 按权重分配 | 服务器性能有梯度 | 权重设置不合理时偏差大 |
| 最小连接 | 分配给当前连接最少的节点 | 请求处理时间差异大 | 节点负载还需要考虑CPU/IO |
| IP Hash | 源IP取模映射 | 需要会话保持 | 节点增减变化频繁 |
总结一下
其实没有银弹。我做过一个DLP接口高可用项目,一开始用了最小连接,发现后端有台机器CPU总是高,后来改成加权轮询配合健康检查,才稳定下来。你想想看:同样的算法,在不同业务特征下表现天差地别。所以关键是要理解每种算法的「偏好性」——轮询偏向公平,加权轮询偏向能力,最小连接偏向空闲,IP Hash偏向绑定。
嗯,到这里算法基础就过完了。下面这张图能帮你快速回顾它们的逻辑关系:
fallback 指令实现,很多开源方案都支持。