连载中 7/20

负载均衡:从轮询到自适应,流量怎么分才均匀

2026-08-25 · 1581 阅读 · 0 评论 · 0 赞

新实例一上来就被打挂

库存服务扩容了两台新机器,流量均匀地打过去——然后新实例接二连三超时。老机器 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 的优雅与陷阱,下一篇见。

503

10 年全栈工程师 · 503咖啡馆主理人

#负载均衡#轮询#平滑加权#最少活跃#自适应

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 5 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞