负载均衡可以放在服务端入口,也可以放在客户端调用侧。两种方式没有绝对好坏,关键是看流量入口、服务治理能力和系统复杂度放在哪里。
1. 服务端负载均衡
服务端负载均衡是最容易理解的一种模式。
Client -> Load Balancer -> Server A
-> Server B
-> Server C客户端只知道负载均衡器的地址,不关心后面有多少台服务器。
常见例子:
- Nginx。
- 云厂商负载均衡器。
- API Gateway。
- Kubernetes Service / Ingress。
这种方式适合对外提供服务的入口层。
2. 服务端负载均衡的优点
客户端简单
客户端只请求一个统一地址。
https://api.example.com后面服务器怎么扩容、下线、迁移,客户端都不用感知。
统一治理方便
入口层可以统一做:
- TLS 终止。
- 鉴权。
- 限流。
- 日志。
- 灰度发布。
- 跨域处理。
- 协议转换。
这些能力放在一个统一入口,比散落在各个客户端里更容易管理。
对外暴露面更小
真实后端实例不需要直接暴露给公网,客户端只访问负载均衡入口。
3. 服务端负载均衡的缺点
服务端负载均衡也有代价。
首先,它可能成为新的瓶颈。
大量 Client -> Load Balancer -> 后端服务如果负载均衡器本身没有高可用,入口挂掉后,后端再多机器也没用。
其次,请求多经过一层转发,会增加一点延迟和链路复杂度。
所以生产环境通常会让负载均衡器本身也做高可用部署。
4. 客户端负载均衡
客户端负载均衡是让调用方自己选择后端实例。
Client -> Service Registry
Client -> Server A
Client -> Server B
Client -> Server C大致过程:
- 服务实例启动后注册到注册中心。
- 客户端从注册中心获取可用实例列表。
- 客户端根据负载均衡算法选择一个实例。
- 客户端直接请求目标实例。
在微服务内部调用里,这种方式很常见。
5. 客户端负载均衡的优点
少一层中间转发
调用方直接请求目标服务,链路更短。
调用方更了解上下文
客户端可以根据业务上下文选择实例。
比如:
- 同机房优先。
- 同区域优先。
- 根据租户或用户做路由。
- 根据接口类型选择不同权重。
更适合内部服务调用
微服务之间调用频繁,如果所有内部请求都走统一网关,网关压力会非常大。
客户端负载均衡可以把流量选择能力下沉到调用侧。
6. 客户端负载均衡的缺点
客户端会变复杂。
它需要处理:
- 服务发现。
- 实例缓存。
- 健康状态。
- 负载均衡算法。
- 超时和重试。
- 版本兼容。
如果每种语言都要实现一遍,会带来 SDK 维护成本。
比如 Java、Go、Node.js、Python 服务都要调用同一个系统,就要保证它们的客户端负载均衡逻辑一致。
7. 两种方式怎么选
可以先这样判断:
| 场景 | 更常见方案 |
|---|---|
| 面向公网用户 | 服务端负载均衡 |
| App / 浏览器访问后端 API | 服务端负载均衡 |
| 微服务内部调用 | 客户端负载均衡或服务网格 |
| 需要统一鉴权限流 | 服务端入口网关 |
| 多语言服务治理复杂 | 服务端网关或服务网格 |
| 调用方需要细粒度路由 | 客户端负载均衡 |
外部流量通常更适合服务端负载均衡,内部服务调用则要结合团队技术栈选择。
8. 还有一种折中:服务网格
服务网格把负载均衡、重试、熔断、限流等能力放到 sidecar 代理中。
业务服务看起来像直接调用:
Service A -> Service B实际链路可能是:
Service A -> Sidecar A -> Sidecar B -> Service B这样可以减少业务代码和 SDK 的复杂度,但基础设施复杂度会提高。
9. 小结
客户端负载均衡和服务端负载均衡的区别,可以抓住一句话:
服务端负载均衡是由统一入口选择后端实例;客户端负载均衡是由调用方自己选择后端实例。
初学时可以先这样记:
- 对外入口多用服务端负载均衡。
- 内部微服务调用可能用客户端负载均衡。
- 服务端方式客户端简单,但入口要保证高可用。
- 客户端方式链路短、灵活,但客户端和 SDK 会复杂。
- 服务网格可以把治理能力下沉到基础设施层。
真正设计系统时,不要只问“用哪种负载均衡”,还要问:服务发现在哪里、健康检查在哪里、重试在哪里、故障隔离在哪里。
留言板