新实例一上来就被打挂
库存服务扩容了两台新机器,流量均匀地打过去——然后新实例接二连三超时。老机器 JIT 热了、本地缓存满、连接池就绪,新机器什么都没准备好就被同样大的流量怼脸。轮询把均匀理解成了每台一样多,但实例的承载能力并不均匀。这一篇从策略选型讲到自适应,把流量分明白。
客户端 LB 与服务端 LB
先分清两类:服务端负载均衡——请求先到 Nginx、LVS 这类独立设施,由它转发,调用方对实例无感知;客户端负载均衡——调用方自己拉实例列表、自己选实例(Ribbon、Spring Cloud LoadBalancer),微服务内部的主流选择,少一跳转发,拓扑也更简单。接入层用服务端 LB,服务间调用用客户端 LB,两层各管一段,别混着比。
常见策略与各自的脾气
| 策略 | 逻辑 | 适合场景 |
|---|---|---|
| 轮询 | 按顺序人人一遍 | 实例性能接近的默认选择 |
| 随机 | 随机挑一台 | 效果接近轮询,实现最简 |
| 加权 | 按权重分流 | 实例性能不均、灰度放量 |
| 最少活跃 | 优先给在处理的请求最少的 | 长短请求混杂 |
| 一致性哈希 | 同参数固定打同一台 | 有状态路由、本地缓存亲和 |
选型口诀:默认轮询;实例不均加权重;长短请求混用最少活跃;缓存亲和用一致性哈希。策略不是越高级越好,行为可预测最重要。
平滑加权:消掉毛刺
加权轮询有个小毛病:权重 5:1:1 时,普通实现会连续五次请求都打给 A 实例,瞬时压力像心电图。平滑加权轮询把请求交错开,长期比例不变,瞬时分布均匀。算法三步:每轮所有节点当前值加自身权重;选当前值最大者出列;选中者减去总权重。
// 平滑加权轮询:权重 A=5, B=1, C=1
// 普通加权:A A A A A B C A A A A A B C —— 连续命中,毛刺明显
// 平滑加权:A A B A C A B A —— 比例不变,瞬时摊平
class SmoothWeightedRoundRobin {
Map<String, Integer> weight, current;
String pick() {
current.replaceAll((k, v) -> v + weight.get(k)); // 1. 每轮加回自身权重
String best = maxByValue(current); // 2. 取当前值最大者
current.put(best, current.get(best) - totalWeight);// 3. 选中者减去总权重
return best;
}
}从静态权重到自适应
静态权重解决不了运行时的变化:GC 停顿、磁盘变慢、邻居抢占,都会让性能均匀的假设失效。自适应的思路是把实时指标反哺给选择器:按最近响应时间动态调权重,慢的自动降温;连续异常的实例临时摘除,过一会儿再探;新实例预热期权重从零爬坡。最小版本用注册中心元数据里的权重加客户端策略就能落地,进阶做法用胜率选节点——先让系统动起来,再逐步进化。
流量分得再均匀,调用本身的问题接踵而来——Feign 的优雅与陷阱,下一篇见。
评论 (0)