想象一下,你开了一家生意火爆的奶茶店。每天排队的顾客从店门口一直延伸到街角。你只有一位店员,忙得脚不沾地,顾客等得怨声载道。
怎么办?答案是:多开几个收银窗口。
但新问题来了------顾客来了,该排哪个窗口?如果大家都挤到第一个窗口,其他窗口闲着,等于没开。如果有人喊"一号窗口没人,去那边",顾客还得自己判断。
这时候,你需要一个叫号机 或者排队引导员。顾客来了,引导员说:"你去一号窗口"、"你去二号窗口"。这样每个窗口的排队人数差不多,效率最高。
这个引导员,就是负载均衡器。
一、什么是负载均衡
负载均衡的核心任务可以用一句话概括:把请求均匀地分给多台服务器。
当你的应用从一台服务器扩展到多台时,就必须解决一个问题:谁来分配请求?分配得不好,有的服务器累死,有的服务器闲死。
负载均衡器就是专门干这个活的。它站在服务器集群的前面,接收所有请求,然后按照某种策略,把每个请求派发给后端的某台服务器。
对用户来说,他只知道一个地址(比如 http://api.example.com),根本不知道背后有多少台服务器、每台的 IP 是什么。所有复杂性都被负载均衡器屏蔽了。
二、一个停车场的比喻
你开车去一个大型停车场。
没有负载均衡:停车场有四个入口,但没有任何指示。你开到东门发现排长队,绕到西门发现也排长队,最后折腾半小时才进去。而且有的入口根本没车用,资源严重浪费。
有了负载均衡 :停车场入口处有一个电子指示牌,实时显示每个区域还剩多少车位。你刚到,指示牌告诉你:"A区还有20个车位,请从1号入口进入"。后面的车看到的是:"B区还有15个车位,请从2号入口进入"。
指示牌保证每个区域的车位被均匀使用,不会出现一个区域停满了、其他区域空空如也的情况。
这个电子指示牌,就是负载均衡器。停车场各个区域,就是后端服务器。
三、负载均衡器的核心职责
| 职责 | 说明 |
|---|---|
| 请求分发 | 把请求均匀分配到后端服务器 |
| 健康检查 | 定期检查后端服务器是否活着,挂了的不再派活 |
| 会话保持 | 同一个用户的请求尽量发给同一台服务器(如果需要) |
| 故障转移 | 某台服务器挂了,自动把它的流量转给其他正常服务器 |
四、常见的负载均衡算法
负载均衡器怎么决定"这个请求该给谁"?有多种策略。
4.1 轮询(Round Robin)
按顺序轮流分配:第一个请求给服务器A,第二个给B,第三个给C,第四个再给A,周而复始。
这就像食堂打饭,窗口依次叫号,公平公正。适合后端服务器配置差不多的情况。
4.2 最少连接(Least Connections)
谁当前处理的请求少,就把新请求给它。
这就像超市收银台,哪个队伍短就去哪个。适合请求处理时间差异大的场景------有的请求快,有的请求慢,光看次数不公平,要看实时压力。
4.3 IP 哈希(IP Hash)
根据客户端的 IP 地址计算一个哈希值,同一个 IP 永远分配给同一台服务器。
这就像学校分班,按学号固定分配。适合需要"会话保持"的场景------比如用户的购物车数据存在某台服务器本地,下次请求还得去那台。
4.4 加权轮询(Weighted Round Robin)
给每台服务器设置一个权重,性能好的多分一些请求,性能差的少分一些。
比如服务器A性能是B的两倍,就给它设权重2,它收到的请求数量是B的两倍。这就像工作量分配:老员工多干点,新员工少干点。
4.5 随机(Random)
随机分配给某台服务器。简单粗暴,但足够均匀。
五、负载均衡器的两种类型
负载均衡器可以部署在软件层面,也可以部署在硬件层面。
5.1 软件负载均衡
用软件程序来实现负载均衡,运行在普通服务器上。
常见的有:Nginx、HAProxy、Spring Cloud LoadBalancer。
优点:便宜(免费开源)、灵活、容易扩展。绝大多数公司都用软件方案。
缺点:性能不如硬件,但普通业务完全够用。
5.2 硬件负载均衡
用专用的物理设备来实现,比如 F5。
优点:性能极高、功能强大、稳定性好。
缺点:非常昂贵(一台几十万甚至上百万),中小公司用不起。
普通公司用 Nginx 或 Spring Cloud LoadBalancer 完全足够了。
六、负载均衡器在微服务中的位置
在微服务架构中,负载均衡器通常出现在两个地方:
6.1 网关层的负载均衡
用户请求先到网关,网关前面有一个负载均衡器,把请求分发给多个网关实例。
用户 → 负载均衡器(如 Nginx)→ 网关集群(多个网关实例)→ 后端服务
这里用负载均衡器的原因是:网关本身需要高可用,不能单点。万一网关挂了,所有请求都进不来。
6.2 服务间的负载均衡
服务A要调用服务B,服务B部署了3台机器。服务A的客户端(比如 OpenFeign)需要决定调用哪一台。
服务A → 负载均衡器(如 Spring Cloud LoadBalancer)→ 服务B集群
Spring Cloud 自带的 LoadBalancer 就是干这个活的。它从注册中心拿到服务B的实例列表,然后用负载均衡算法选一个去调用。
七、健康检查的重要性
负载均衡器把请求分给后端服务器,但如果某台服务器已经挂了,还给它发请求,用户就会收到错误。
所以负载均衡器必须定期检查后端服务器的健康状况。通常的做法是:每隔几秒去访问服务器的一个健康检查接口(比如 /actuator/health),如果能正常返回,就认为活着;如果连续几次失败,就把这台服务器从可用列表中踢出去,不再给它派活。
等它恢复后,负载均衡器会重新把它加回来。
这就像班长点名:每天检查谁到校了,没到的就不安排值日。
八、会话保持问题
负载均衡器带来的一个麻烦是:如果用户的登录信息存在某台服务器本地,下次请求被分到另一台服务器,用户就得重新登录。
解决方案有三种:
方案一:共享 Session。把用户信息存到 Redis,所有服务器共享。这是最常用的方案。
方案二:会话保持。用 IP Hash 算法,让同一个用户的请求始终去同一台服务器。缺点是如果那台服务器挂了,用户会话就丢了。
方案三:无状态设计。服务器不存任何用户状态,所有必要信息都放在 Token 里(比如 JWT)。这是微服务最推崇的方案。
九、Nginx vs Spring Cloud LoadBalancer
| 对比项 | Nginx | Spring Cloud LoadBalancer |
|---|---|---|
| 位置 | 网关层 | 服务间调用层 |
| 协议 | HTTP、TCP | HTTP(基于服务发现) |
| 配置方式 | 配置文件 | 代码 + 配置 |
| 服务发现集成 | 需手动配置上游 | 自动从注册中心获取 |
| 适用场景 | 入口流量分发 | 服务间调用负载均衡 |
两者不是替代关系,而是配合关系。Nginx 负责入口层的流量分发,Spring Cloud LoadBalancer 负责服务内部调用时的负载均衡。
十、总结
负载均衡器是微服务架构中不可或缺的基础组件。
它的核心价值可以概括为三句话:
-
均匀分配:让多台服务器分担压力,避免单点过载
-
自动容错:发现某台服务器挂了,就不给它派活
-
对外统一:用户只看到一个地址,后端怎么扩展都不影响
回到奶茶店的比喻:负载均衡器就是那个叫号引导员。顾客来了,引导员说"去一号窗口",下一位说"去二号窗口"。哪个窗口的店员请假了,引导员就不往那边派单。顾客不需要知道有几个窗口、谁在上班,他只知道"去叫号机那儿领号就行"。
在微服务架构中,负载均衡器就是那个叫号引导员。它让服务可以水平扩展,让系统可以扛住更大的流量,也让某台机器挂掉时用户几乎无感知。