为什么需要
单台服务器的处理能力有上限。当流量增长,有两个方向:
- 纵向扩展(Scale Up):换更强的机器(更强的 CPU、更多内存)。简单,但有物理上限,且成本增长快;
- 横向扩展(Scale Out):加更多机器。理论上无上限,但需要把流量分配给它们——这就是负载均衡。
工作层次
四层负载均衡(L4)
工作在传输层(TCP/UDP)。基于 IP + 端口做转发。
它不解析 HTTP 内容,只看数据包的地址信息。处理速度快,开销小。
七层负载均衡(L7)
工作在应用层(HTTP)。可以解析 HTTP 请求,基于 URL、主机名、Cookie、Header 等做路由。
灵活性强(如把 /api 的请求转发到 API 服务器,把 /static 的请求转发到静态资源服务器),但处理开销大。
常见算法
轮询(Round Robin):依次分配给每台服务器。简单,但不考虑服务器的实际负载和性能差异。
加权轮询:给性能强的服务器分配更高的权重。
最少连接(Least Connections):把新请求发给当前连接数最少的服务器。适合长连接场景(如 WebSocket)。
源地址哈希:根据客户端 IP 计算哈希,保证同一客户端总是落到同一服务器。这提供了会话保持(Session Affinity)——但缺点是不利于扩展,且客户端分布不均时容易失衡。
一致性哈希:改进方案。把服务器和请求都映射到一个哈希环上,服务器增减时只影响相邻的一小部分请求,而不是全部重新分配。
健康检查
负载均衡器必须持续检查后端服务器的健康状态:
- 主动检查:定期发送探测请求(如请求
/health); - 被动检查:根据真实请求的响应情况判断(如连续多次超时或返回 5xx 就标记为不健康)。
发现故障后,把该服务器从可用列表中摘除;恢复后重新加入。
会话状态问题
如果应用把用户会话存在服务器本地内存中,那么负载均衡导致用户请求落到不同服务器时,会话就丢失了。
三种解法:
一、会话保持:让同一用户总是访问同一台服务器。简单,但破坏了扩展性和容错性(该服务器宕机,其上的会话全丢)。
二、共享存储:把会话存到外部的共享存储(如 Redis、数据库)。服务器变成无状态的,可以任意扩缩容。这是推荐做法。
三、无状态设计:用 JWT 一类的令牌,把状态放在客户端。
负载均衡器本身的高可用
负载均衡器是单点故障——它挂了,整个服务就不可用了。
解法:
- 多台负载均衡器做主备或集群;
- 使用 VIP(虚拟 IP)配合 VRRP 等协议实现故障切换;
- 或者使用 DNS 轮询 + 健康检查,在 DNS 层面做故障转移(切换较慢)。
一个进阶话题
在微服务架构中,负载均衡常常下沉到服务网格或客户端负载均衡:每个服务自己维护可用实例列表并选择目标,从而避免中心化的负载均衡器成为瓶颈。
说明:本文为分布式系统架构的公开知识整理。