客户端负载均衡 vs 服务端负载均衡
这一章我们来聊一个经典话题:负载均衡到底应该放在客户端,还是服务端?
我见过不少团队在这上面纠结很久,甚至花了大价钱买硬件负载均衡器,结果发现业务场景其实用客户端就搞定了。
说白了,没有银弹,只有合适的姿势。
核心差异:谁在做决策?
先讲一个最直观的区别。
服务端负载均衡,就是请求先打到中间层(比如 Nginx、HAProxy、硬件 F5),由中间层决定转发给哪个后端实例。
客户端只管发请求,自己对后端列表一无所知。
客户端负载均衡,是客户端自己维护一份可用服务列表,直接在本地选一个节点发请求。
没有中间的“裁判”,客户端自己就是裁判。
一句话总结:
服务端模式:客户端 → 中间层 → 后端集群
客户端模式:客户端 → 后端集群(通过本地规则选择)
我记得刚做微服务那会儿,用的是传统 Nginx 做反向代理。后来接触 Spring Cloud,发现 Ribbon 直接在客户端做负载均衡,当时还有点不适应。心想:客户端怎么能自己决定往哪发?这不乱套了吗?
后来用多了才明白,各有各的场景。
一张图看懂两种模式
下面这张图把核心流程画清楚了。左边是服务端模式,右边是客户端模式。
你一看就知道流量是怎么走的。
场景对比:什么时候用什么?
这两者不是简单的“谁更好”,而是看你的架构阶段和团队能力。
| 维度 | 服务端负载均衡 | 客户端负载均衡 |
|---|---|---|
| 部署方式 | 需要在集群前加一层代理(硬件或软件) | 客户端 SDK 自带,无需额外部署 |
| 服务发现 | 通常需要配合 DNS 或健康检查 | 内置注册中心(如 Eureka、Consul) |
| 故障感知 | 依赖中间层的健康检查 | 客户端可以本地感知,更及时 |
| 流量控制 | 统一管控,黑白名单、限流方便 | 分散在客户端,治理难度大 |
| 语言绑定 | 无语言限制 | 不同语言需各自实现 |
| 典型产品 | Nginx、HAProxy、AWS ALB | Ribbon、gRPC Load Balancing |
你看这个表,很清晰了。
- 服务端模式强在统一管控,适合传统架构、多语言异构、需要集中安全策略的场景。
- 客户端模式强在反应快、无单点、适合云原生和微服务。
我在项目中遇到过这样的事:一个团队先用 Nginx 做负载均衡,后来为了提升容量,不断加后端实例。结果 Nginx 成了瓶颈,虽然加了多台 Nginx 做负载均衡的负载均衡……你懂的,套娃。
后来切换到客户端模式,每个 Java 服务直接用 Ribbon 拿到实例列表,性能一下就上来了。
个人建议:
如果你用的是 Spring Cloud、Kubernetes、gRPC 这类强服务发现体系,优先考虑客户端负载均衡。
如果你的客户端是浏览器或原生端,或者你需要做南北向流量管控(比如公网入口),服务端模式更合适。
实战避坑:服务端模式的“单点味道”
很多人觉得服务端模式有单点,这是误解。
Nginx 和 HAProxy 都可以做集群,比如 Keepalived 做 VIP 漂移,或者直接用 DNS 轮询多个入口。
但有一个隐藏坑:连接数堆积。
我曾经遇到过一个案例,Nginx 后端有 20 个实例,每个实例的 max_connections 是 500。理论上可以支撑 10000 并发,结果到了 6000 就大面积超时。
查了半天才发现是 Nginx 的 worker_connections 没调大,上行连接数先满了。
嗯,这种细节在客户端模式中反而不会出现——每个客户端自己发起连接,压力天然分散。
实战避坑:客户端模式的“版本混乱”
客户端负载均衡最大的挑战是一致性。
- 不同语言的客户端需要维护不同的 LB 实现
- 升级 LB 规则时,必须更新所有客户端
- 新加入的后端实例,如果注册中心推得不及时,客户端可能不知道
我曾经踩过的坑:
有一次我们在服务上线时,新实例已经注入了 Eureka,但有一个老版本的客户端没有及时拉取更新,还把请求打到已经下线的实例上,导致大量 502。
后来痛定思痛,强制所有客户端一定开启心跳和本地缓存过期机制,并加了重试熔断。
怎么选?我的决策框架
你不需要记住所有细节,只需要记住下面这个判断逻辑:
- 你的客户端可控吗?
→ 可控(比如你自家写的微服务) → 客户端负载均衡
→ 不可控(浏览器、第三方) → 服务端负载均衡 - 你的后端实例会频繁变化吗?
→ 变化频繁(K8s pod 自动伸缩) → 客户端模式(感知快)
→ 变化不频繁(固定服务器列表) → 都可以 - 你们团队有统一的语言栈吗?
→ 统一(比如全是 Java/Go) → 客户端模式方便
→ 多语言 → 服务端模式更省心 - 你需要做全局流量治理吗?
→ 需要(如灰度发布、请求染色) → 服务端模式更利于统一管控
一句话收尾:
服务端模式让架构“整洁”,客户端模式让系统“敏捷”。
没有的对错,只有适合不适合。