§ 5.5 · Section

负载均衡 LB

Load Balancing · L4 / L7 · HTTP 见 RFC 9110(一致性哈希无 RFC)

第 5 章讲到这里,四位主角已经出场:交换机、路由器、网关与光猫、防火墙,它们分别解决了"同一条街怎么送""跨城怎么送""出门那道门""谁能进门"。但还有一个问题没回答:当一个网站的访问量大到一台服务器根本接不住的时候,怎么办?答案是:多买几台服务器,然后在它们前面站一个"分单员",把涌进来的请求分给不同的服务器——谁也别闲着、谁也别累趴。这个分单员,就是本节的主角:负载均衡(Load Balancer,简称 LB)。这一节用"奶茶店门口的分单员 / 银行的叫号机",把四层与七层、五种分发算法、健康检查、会话保持全部讲透,也为整个第 5 章收官。

生活场景
🍵 奶茶店排队:一列队伍 vs 三个窗口

想象一家周末爆满的奶茶店。如果店里只有一位收银员,队伍会从柜台一直排到门外,店员手忙脚乱,顾客骂骂咧咧——这就是"一台服务器扛不住"的样子。

聪明的店会把柜台开成三个窗口。门口站着一个分单员:每个客人进门,他扫一眼三个窗口的排队情况,喊一声"3 号窗口";哪个窗口空了,就把下一位客人派过去;1 号窗口挂出"设备检修"的牌子,他就绕开它;有位熟客每次都想去 2 号窗口,因为那儿的店员记得他的口味,分单员也记住了,总把他往 2 号窗口引。

这一节要讲的负载均衡,就是这个分单员的职业化版本。它干的事一句话:把请求(客人)分给不同的后端服务器(窗口),让整个系统既不让任何一台累趴,也不让任何一台闲着。

先把这一节的术语翻译成人话

和前面几节一样,这一节也是术语密集。好消息是:负载均衡的每个概念,几乎都能在"奶茶店分单员 / 银行叫号机"这套场景里找到一一对应的东西。先过一遍这张表,读完全文再回来重读一次,效果最好。

术语换成大白话生活里对应的东西
负载均衡(Load Balancer,缩写 LB)说白了就是"站在服务器门口的排单员"奶茶店门口喊"3 号窗口"的分单员
后端服务器(Backend Server)说白了就是"真正干活的那几台机器"窗口后面做奶茶的店员
虚拟 IP(Virtual IP,VIP)说白了就是"对外只亮一个公共门牌"店门口挂的"本店"招牌,不问后面有几个窗口
四层负载均衡(L4)说白了就是"只看你取的是几号窗口"叫号机只看号,不看你要办什么业务
七层负载均衡(L7)说白了就是"听你要办什么事再分"医院分诊台:问清哪不舒服,再分到内科还是外科
轮询(Round Robin)说白了就是"挨个叫号,轮流来"窗口 1、2、3、1、2、3 轮流接客
加权轮询(Weighted Round Robin)说白了就是"老手多接、新手少接"老师傅窗口接 3 个,实习生窗口接 1 个
最少连接(Least Connections)说白了就是"谁空闲派给谁"理发店:哪把椅子空着,新客人就去哪
IP 哈希(IP Hash)说白了就是"同一个 IP 永远分到同一台"熟客总去 2 号窗口,因为那儿的店员记得他
一致性哈希(Consistent Hashing)说白了就是"加窗口、减窗口,影响最小"公交环线上新加一站,只有离它最近的那段乘客受影响
健康检查(Health Check)说白了就是"定期确认这窗口还开着吗"分单员隔几分钟喊一嗓子"都还开着吗"
心跳(Heartbeat)说白了就是"窗口自己主动举手报到"店员每做几杯就举一下手"我还在"
会话保持(Sticky Session)说白了就是"同一个客人的一串事,始终在同一窗口办"熟客的订单永远记在 2 号窗口
故障转移(Failover)说白了就是"窗口塌了,客人转给别的窗口"1 号窗口停电,客人全部改去 2、3 号

这一节可以用一句话串起来:负载均衡是"奶茶店门口的分单员",它对外只亮一个门面(虚拟 IP),对内按一套规则把请求分给一群后端服务器(分发算法),并且时不时确认每台后端还活着(健康检查)。其余全是细节。

一台服务器为什么扛不住:先把问题看明白

要理解负载均衡,得先理解它的反面:一台服务器为什么扛不住?回指 § 4.5,一个请求从发出去到拿到响应,成本由两部分组成:一个网络来回的时间(由距离决定)加上服务器处理的时间(由服务器性能和业务复杂度决定)。问题在于:网络来回的时间是"一个请求一份",而服务器处理的时间是"大家抢着用"的。

打个比方,食堂打饭:一个窗口一分钟能做 10 份饭。中午全校 3000 人同时下课涌过来,一个窗口一分钟只能接 10 份——后面的同学只能干等,队伍越来越长。换成大白话:请求来得太快,服务器处理不过来,后面的人就得排队,这就是排队时延(§ 1.6 讲过时延的组成)。

具体数字换成人话:一台普通服务器每秒能处理的请求数因配置而异,量级大概在几百到几千(经验量级,具体因机器而异)。而一个热门网站的高峰请求量可以到每秒几万甚至几十万——相当于一个打饭窗口要面对整座城市的人。别说一秒,一眨眼都接不住。一台服务器扛不住,通常有这三个症状,一个比一个严重:

那换个思路:买一台更贵的服务器行不行?这叫垂直扩展(Scale Up)——把小面包车换成重卡。有用,但有天花板:单台机器的 CPU、内存、带宽都有物理上限,而且越往上越贵。换成大白话:一辆卡车再大也有载重上限,而且重型卡车贵得离谱。

于是有了另一条路:水平扩展(Scale Out)——买 100 辆小面包车并行送货。对应到网站,就是多买几台服务器,让它们一起干活。可是新问题来了:客人怎么知道该找哪辆车?总不能要求用户自己记住"我这次去 3 号服务器"。总得有个东西站在前面,替客人做选择。这个东西,就是负载均衡器。

【单机 vs 集群 + 负载均衡:一张图看懂】

  单机时代:                        集群时代:
  用户 ──→ 一台服务器              用户 ──→ 负载均衡器(一个门面)
                                        ├─→ 服务器 A
                                        ├─→ 服务器 B
                                        └─→ 服务器 C

  一台挂了 → 全站没了              一台挂了 → 其他两台继续接客
  流量一涨 → 排队到崩溃           流量一涨 → 加两台机器就扛住

注意集群那一侧的关键词:"一个门面"。用户面对的永远只有一个入口,至于入口后面站着几台服务器、今天是不是又加了两台,用户完全无感。这个"门面"就是负载均衡器存在的意义——它把"一群服务器"包装成"一台服务器"给你用。

用下面的时延账本自己算一笔:假设请求越来越多,把排队的时间加进去,看看总时延是怎么涨上去的——你会直观看到"一台服务器面对一大群人"时,时间是怎么被队伍吃掉的。

分单员到底在干什么:负载均衡的三件事

负载均衡(Load Balancer)这个词听着玄,其实就是"站在服务器门外的分单员"。它的完整职责可以拆成三件事,记住这三件事,你就抓住了它的全部工作:

这里最关键的一点是:对用户来说,一切透明。用户只跟"一个门面"打交道,门面背后是 10 台还是 100 台服务器,他完全没有感觉。就好比你去银行办业务:取号、排队、被叫号,你根本不会去数大厅后面到底有几个柜员在忙。

顺便澄清一个常见误会:负载均衡器自己很轻。它不处理业务逻辑、不查数据库、不做奶茶,它的全部价值在于"让后面那排服务器忙得均匀"。换成大白话:分单员自己不动手做奶茶,他只是保证三个窗口都不闲着、都不累趴。这也意味着,加一台负载均衡器不等于加了算力——它只是让已有的算力被用得更均匀(这一点在"常见误区"那节还会回来说)。

还有一点值得注意:负载均衡器挑出后端之后,就把请求原样转过去——这个"选下一棒"的动作,和 § 5.2 路由器查路由表选下一跳的思路一模一样。都是"不掌握全程,只决定下一步交给谁":路由器把包交给下一跳就不管了,负载均衡器把请求交给某台后端也就不管了(除非它同时是七层反向代理)。不妨这样想:路由器是"跨城接力"的分单员,负载均衡器是"同一栋楼里"的分单员。

Analogy · 奶茶店分单员:负载均衡的全部真相

如果你只记住这一节的一个类比,请记住这个。

一家奶茶店开出了三个制作窗口(1 号、2 号、3 号),每个窗口后面各有一位店员在调奶茶。门口站着分单员。

① 他只看排队情况,不关心客人点了什么。客人进门,他只需要判断"哪个窗口最空、该去几号"——至于这杯是珍珠奶茶还是柠檬茶,那是店员的事。四层负载均衡就是这样:只看"这个请求要发往哪个 IP 和端口"(送到哪个窗口),不拆开看内容。

② 他只负责分配,自己不动手做奶茶。分单员不碰原料、不做饮品,他的全部价值在于让三个窗口忙得均匀。负载均衡器也一样:它不处理业务逻辑,只负责把请求"调度"到合适的服务器——真正的体力活在后面那排服务器身上。

③ 哪个窗口挂了,他必须知道。如果 1 号窗口的机器坏了还继续往里派客人,客人会堵死在窗口前。所以分单员要么每隔一会儿喊一声"都还开着吗",要么让每个窗口主动举一下手——这就是健康检查。

把这三个特征记住,这一节就学完一半了:负载均衡器 = 一个门面(VIP)+ 一套分派规则(分发算法)+ 一套健康检查。

四层 vs 七层:只看窗口号 vs 听你要办什么

现在到了这一节最重要的一张牌:四层(L4)与七层(L7)负载均衡。这两个数字不是随便起的,它们来自前面讲过的分层模型:四层对应 OSI 七层模型(§ 2.1)里的第 4 层"传输层"(在 TCP/IP 四层模型(§ 2.2)里叫传输层),七层对应第 7 层"应用层"(在四层模型里叫应用层)。数字的含义是"负载均衡器在协议栈的哪一层做决定"。

四层负载均衡(L4):它只看到 IP 地址和端口号(比如 203.0.113.88:443),然后把这个连接原样转给某一台后端。它不拆开包裹看里面的内容。说白了,它就像只认号的叫号机:客人来了,看一眼号单上是"A 类还是 B 类",就告诉你去 1-3 号窗口还是 4-6 号窗口——至于你要办存款还是贷款,它不管,那是窗口里柜员的事。

七层负载均衡(L7):它能拆开 HTTP 报文(回指 § 4.5:请求行、请求头、请求体),看到 URL 路径、Host 域名、Cookie、甚至请求体里的内容。于是它能做更精细的决策——比如"图片请求去图片服务器组,下单请求去订单服务器组"。说白了,它像医院的分诊台:护士先问你哪儿不舒服,再决定把你分到内科、外科还是眼科。一个只看"送到哪个窗口",一个听"你要办什么事"——这就是 L4 和 L7 最本质的区别。

代价与收益也很直白:L4 不拆包,所以快、省资源、能扛海量连接(每秒百万级连接是常见量级,具体因设备而异);L7 要拆包解析,所以慢一点、吃 CPU,但换来"按内容分流"的灵活。真实世界里两者经常串起来用:入口先放一台 L4 快速分流,把请求按端口分到不同的服务器组;到了服务器组里面,再用 L7 按 URL 做细粒度分流。这就像机场:先按航班号把你分到 A 区还是 B 区(粗分),登机口再按座位号细查(细分)——分层接力,和 § 2.1/§ 2.2 讲的分层思想一脉相承。

四层 L4七层 L7
在哪一层做决定传输层(§ 2.2 四层模型的第 3 层)应用层(§ 2.2 四层模型的第 4 层)
看什么信息IP 地址 + 端口号HTTP 内容:URL、Host、Cookie、请求体
会不会拆包不拆,原样转发要拆开报文看内容
速度与开销快、省资源慢一点、吃 CPU
能做什么精细决策按端口分流(如 443 去 HTTPS 组)按路径/域名/Cookie 分流(如 /img 去图片组)
生活类比叫号机只看号单类型分诊台护士听你描述病情

一个技术标注:这里说的 HTTP 规范编号是 RFC 9110(回指 § 4.5:请求报文、头部字段、状态码都定义在这一系列文档里)。而"L4 负载均衡""L7 负载均衡"这两个词本身没有自己的 RFC——它们不是独立的协议,而是"在协议栈第几层做转发"的两种工作方式,身份来自 § 2.1/§ 2.2 的分层模型本身。

还有一个实战中绕不开的细节:七层负载均衡器常常顺便当一把"反向代理"(Reverse Proxy)。这个词在 § 4.5 的术语表里出现过——反向代理说白了就是"你以为在跟店家说话,其实先经过了一个前台":用户对着负载均衡器说话,负载均衡器再替他去跟后端说话,把后端服务器的真实身份完全藏起来。既然七层 LB 本来就要拆开 HTTP 看内容,它往往就把 HTTPS 的加解密也顺手做了——这招叫 TLS 终结(也叫 SSL offload,回指 § 4.4 的 TLS 握手):用户和 LB 之间走加密,LB 和后端之间可以是明文,后端每台机器都省掉了做加解密的开销。好处是省算力,代价是"加密只到 LB 为止"——如果 LB 和后端之间的链路不安全,这段内容就相当于裸奔。所以正经部署里,LB 到后端之间通常走加密或至少走内网,这个细节在安全要求高的系统里很重要。

分发算法之一:轮询与加权轮询

负载均衡器接到一个请求,到底分给谁?靠的是分发算法(也叫调度算法)。这一节开始逐个拆,每个都配一个生活类比。

最朴素的算法是轮询(Round Robin)挨个叫号,1、2、3、1、2、3,轮流来。三个窗口,第一个客人去 1 号,第二个去 2 号,第三个去 3 号,第四个又回 1 号……大家机会均等,谁也别想抢戏。打个比方,食堂开饭,几个窗口轮流叫号;或者洗车店三个工位轮着接车,一辆一辆排过去。

轮询的好处是简单、公平、不用动脑子;但它有个前提假设:所有后端都一样——配置一样、能力一样、每个请求的重量也一样。现实里这个假设经常不成立。想象 1 号窗口是干了十年的老师傅,一杯奶茶 30 秒搞定;2 号窗口是第一天上班的实习生,一杯要 2 分钟。轮询还是"一人一杯",结果老师傅窗口闲得擦台子,实习生窗口排成长队。

于是有了加权轮询(Weighted Round Robin):给每个后端一个权重,权重大的多分活。换成大白话:老师傅窗口权重 3,实习生窗口权重 1,那么每 4 个请求里,3 个给老师傅、1 个给实习生。这样快的窗口多干活,慢的窗口少干活,整体吞吐反而最大。就像流水线(车间)上,快手多分几件活、慢手少分几件,整条线才跑得最快;也像外卖平台给熟手骑手多派几单。

什么时候用轮询系?当你的后端机器配置差不多、而且每个请求消耗的资源也差不多的时候。典型的例子:一堆相同配置的服务器,接口都是"读一个缓存再返回",每个请求耗时都差不多——轮询就是最合适的选择,简单又够用。

分发算法之二:最少连接

轮询有个看不见的坑:它假设"每个请求的重量都一样"。但真实网站的请求,轻重悬殊得很:有的请求看一眼就完(比如一张静态图片),有的请求要查半天(比如一次复杂的搜索、一个大数据量的报表)。如果轮询平均派发,很可能把好几个"重请求"都派到同一台机器上——这台机器累死,别的机器闲死。

于是有了最少连接(Least Connections)新来的请求,给"当前正在处理的连接数最少"的那台后端。说白了就是"谁空闲,就派给谁"。哪个窗口手上的活儿最少,下一位客人就去哪个窗口。

打个比方,理发店不太可能用"挨个叫号"——你更愿意去那个空着的椅子,或者手头客人最少的师傅那儿。餐厅里,领班会把手上的活儿分给"手上桌数最少"的服务员,而不是机械地轮一圈。这些都是"最少连接"的直觉:看谁闲,给谁派活。

为什么它比轮询更能反映真实负载?因为"正在处理的连接数"是动态的:一台机器刚处理完一个重请求,它的连接数就降下来了,下个请求就会被派给它;一台机器正被一个大请求卡住,它的连接数一直没降,就不会再被派新活。换成大白话:轮询是按人头轮流,最少连接是按忙闲分配——后者的信息量更大。

不过它也有局限:连接数并不完全等于"忙不忙"——一个连接可能极轻,也可能极重。所以工程上还演化出更精细的变体:加权最少连接(再叠加机器的能力差异)、按响应时间、按 CPU 使用率、按内存使用率……这些是各家实现不同的工程实践细节,这里不展开编造数值。你只需要记住:从"轮询"到"最少连接",本质上是"从只看人头,到看忙闲"的进步。

分发算法之三:IP 哈希——同一客人总去同一窗口

前面两种算法(轮询、最少连接)都不关心"请求是谁发来的"。但有些场景偏偏需要"同一伙人总去同一台服务器"。这就轮到IP 哈希(IP Hash)登场了。

它的做法很简单:把请求的来源 IP 地址,通过一个哈希函数算出一个数字,再用这个数字决定分给哪一台后端。同一个 IP 永远算出同一个数字,所以同一个用户(至少是同一个 IP 的用户)永远被分到同一台服务器。

哈希(Hash)这个词听着玄,其实就是"把任意输入,变成一个小范围内的数字"。打个比方,图书馆把每本书的书名翻译成一个架号(分类号)——同一本书永远落在同一排书架上,但随便换一本书,架号就完全不同。哈希函数干的就是这件事:输入"你家 IP",输出"3 号服务器";输入"我家 IP",输出"7 号服务器"。

IP 哈希的价值在于:它是"天然的会话保持"。同一个用户连续发来的请求,都会被分到同一台服务器,不需要 Cookie、不需要额外记忆,全靠算。换成大白话:分单员记住"这位熟客总去 2 号窗口"——只不过他记的不是人,而是这个人的 IP。

但它的缺点也很明显:① 某台服务器挂了,所有被哈希到它的用户集体"改道"或遭殃;② IP 本身不稳定——家里上网的 IP 是运营商动态分配的,换个 WiFi、手机从 WiFi 切到 4G/5G,IP 就变了(回指 § 3.5:NAT 还会让一屋子设备共用同一个公网 IP)。相当于熟客换了件衣服,分单员就认不出来了,又把他当成新客随便派。

所以 IP 哈希通常用在"不需要精确会话、只想让同一用户尽量稳定"的场景,或者在更复杂的哈希变体里当零件。它本身不算高级,但它是理解下一个算法(一致性哈希)的垫脚石。

分发算法之四:一致性哈希——加减机器影响最小

哈希派发有个隐藏的大问题,普通哈希完全没解决。先看普通哈希怎么算:假设有 5 台服务器,编号 0 到 4,把 IP 哈希出来的数字除以 5 取余数,余数就是服务器编号。一切正常,直到——你加了第 6 台服务器。

一改成"除以 6 取余数",几乎所有人的余数都变了:本来该去 3 号的人,可能改去 0 号;本来该去 4 号的人,可能改去 2 号。换成大白话:学校按"学号除以班级数取余数"分班,班级数从 5 个变成 6 个,几乎全班同学的班级都要重分一遍。对缓存类系统这是灾难:所有缓存全部"够不着"了(缓存分布在各台机器上,用户改去了别的机器,就命不中缓存),数据库瞬间被查爆——这就是传说中的"缓存雪崩"。

一致性哈希(Consistent Hashing)就是来解决这个问题的。它的思路是:把所有服务器和所有请求,都放到一个巨大的"数字圆环"上(0 到 2 的 32 次方减 1,可以理解成一圈刻度)。每台服务器在环上占一个点;每个请求也算出一个点,然后"顺时针"找第一个遇到的服务器——它就是接收者。

【一致性哈希:一个圆环上的故事】

  把 0 ~ 2^32-1 想象成一圈刻度,首尾相连:

        0 ──────────────── 服务器A(100)
        │                     │
   服务器B(50)              服务器C(150)
        │                     │
        └──── 请求1(80) ──────┘

  请求 1 落在刻度 80,顺时针遇到的第一个服务器是 C(150)
  → 请求 1 由服务器 C 处理

  现在新增一台服务器 D(90),正好落在 80 和 100 之间:
  原本去 A(100) 的、落在 (80, 90] 这一小段的请求,改去 D;
  其余所有请求完全不动。

现在看加机器的影响:新服务器只"接住"它和它逆时针方向前一台之间的那一段请求,其他请求一个都不动。打个比方,环形公交线路上有 A、B、C、D 四个站,你住在 C、D 之间,每天坐环线在下一站换乘。现在线路上新加了一个站 X(恰好加在 C 和 D 之间):受影响的只有"本来要在 C 站换乘、现在能在 X 站换乘"的那一小段乘客——离新站最近的那部分人。其他人该怎么坐还怎么坐。这就是"加机器只影响一小部分请求"的全部秘密:影响范围 = 新机器到它前面那台机器之间的那一小段圆弧。

减机器同理:一台机器下线,只有"它顺时针方向的下一个区间"要接住它的活,别的不受影响。普通哈希加一台机器,几乎所有人重新洗牌;一致性哈希加一台机器,只有一小段圆弧重排——这就是两者的本质区别。

普通哈希一致性哈希
怎么定映射取余数:hash % 服务器数量环上落点 + 顺时针找最近服务器
加一台机器几乎所有人的映射都变只有一小段圆弧的请求变
减一台机器几乎所有人的映射都变只有被减机器顺时针的下一段受影响
缓存/连接受影响面几乎全部失效只有一小部分需要重排
生活类比按学号除以班级数分班,改班级数全班重分公交环线加一站,只有邻近那段的乘客换乘变

技术标注,这句要划重点:一致性哈希是工程实践概念,没有对应的 RFC——它最早出自 1997 年 Karger 等人关于分布式缓存的一篇论文,后来被无数系统(分布式缓存、负载均衡、消息队列)广泛采用,但它从来不是 IETF 标准化的协议,也没有一个叫"一致性哈希"的 RFC 编号。你在文档里看到 "consistent hashing",知道它是一种算法思路就够了。

工程上还有一个常见的补丁叫虚拟节点:让每台真实服务器在环上不占一个点,而是占好几个点(分散着放)。说白了,就是让每台机器的"势力范围"在环上铺开,这样即使几台机器恰好挤在一起,也不会出现"环上一大半归一台管、别的闲死"的极端情况。这也是工程实践的细节,各家实现不尽相同——你只需要记住:环上的点是可以人为撒的,撒得均匀,分配就均匀。

回到负载均衡:用一致性哈希做分发的好处,正是"扩容缩容时,现有连接和缓存尽量不受影响"——这也是为什么缓存集群几乎必用一致性哈希。一句话记法:普通哈希怕"变数",一致性哈希为"变数"而生。

健康检查:分单员怎么知道哪个窗口还开着

无论用哪种算法,都有一个前提:派活的那台后端必须是活的。如果分单员把客人派给一个已经塌了的窗口,客人会卡死在那里。所以负载均衡器必须定期确认每台后端的状态——这就是健康检查(Health Check)

健康检查有两种主流做法:

发现不健康之后呢?摘除(drain / remove):负载均衡器不再往这台后端派新请求。好比窗口挂出"暂停服务"的牌子,分单员绕开它。等它恢复健康(连续几次探测成功),再翻回"营业中"的牌子,重新接客。这个"摘除—恢复"的循环,是负载均衡器区别于"一个只会转发的交换机"的核心——没有健康检查,再好的算法也会把请求发给死掉的服务器。

顺带认识一个状态码:当所有后端都挂了或都在维护时,负载均衡器自己会向用户返回 503 Service Unavailable(服务不可用,回指 § 4.5:5xx 是服务器这边出了问题)。用下面的组件,点开这个状态码以及几个相关状态码,看看它们的官方含义:

一个容易忽略的细节:健康检查是有延迟的。探测是"每隔几秒"一次,不是每毫秒一次。所以一台后端刚挂掉的那几秒里,可能还有几个请求被派给它——这几个请求就失败了。这解释了为什么生产环境总说"负载均衡不能保证零故障,只能保证故障影响面小"。

会话保持:登录状态怎么办

现在把前面所有知识拼起来,看一个真实场景:你在购物网站登录了,然后点了下一页,结果被要求重新登录。怎么回事?

回指 § 4.5:HTTP 是无状态的,登录状态靠 Cookie 维持。服务器在响应里塞一个 Set-Cookie,浏览器记住这个"寄存牌",下次请求带上它。问题在于:寄存牌(Cookie)在你手里,但寄存柜(服务器上的会话数据)可能只有某一台服务器有。如果第一次请求去了服务器 A,A 把"你已登录"记在自己那儿;第二个请求被负载均衡分到了服务器 B——B 翻了翻自己的抽屉,没你的档案,只好让你重新登录。用户会崩溃的。

解决这个问题的办法有三条路,正好对应三种不同的哲学:

sticky session共享会话存储无状态 + 客户端存储
会话数据存在哪某一台后端服务器所有后端都能访问的公共存储客户端自己的 Cookie / 令牌里
任何一台后端都能接客吗不能,只能去被粘住的那台能,谁都能查档能,谁都能验卡
那台后端挂了会怎样这位用户的会话一起没了换一台照样服务换一台照样服务
负载均衡分配自由度高吗低,被"粘住"束缚高,随便分高,随便分
生活类比熟客固定窗口,师傅记得口味所有窗口共用一个档案柜顾客随身带卡片,到哪都能验

注意一个常见混淆:"会话保持(sticky session)"只是三种方案里的第一种,很多人却把它当成唯一的办法。实际上现代大型网站几乎不用纯 sticky,因为"把用户粘死在一台机器上"恰恰破坏了水平扩展的意义(机器一挂,用户会话就没了;机器一多,分配就不均匀)。主流做法是共享会话存储或无状态方案——让"任何一台服务器都能服务任何用户"。

负载均衡器长什么样:硬件、软件、云

负载均衡是一个"角色",不是某一种特定的盒子。同一个角色,有三种常见的"扮相":

硬件负载均衡软件负载均衡云负载均衡
典型代表F5 BIG-IP、Citrix Netscaler 等专用设备Nginx、HAProxy、LVS 等程序AWS ELB、阿里云 SLB、腾讯云 CLB 等
形态一台专用的硬件盒子装在普通服务器上的软件云平台提供的托管服务
优点吞吐大、稳定、有专用芯片加速便宜、灵活、可深度定制按量付费、自动扩缩、免运维
缺点贵、升级要换硬件要自己装、自己调、自己养绑定云厂商、配置自由度有限
生活类比机场专用安检设备:贵但快手机装个叫号 App:便宜灵活活动请的兼职分单员:按小时算钱

还有一个最古老也最土的办法:DNS 轮询。回指 § 4.2 的 DNS 解析:一个域名本来对应一个 IP,DNS 轮询让一个域名对应多个 IP,DNS 服务器每次解析时轮流返回其中一个。好比校门口问路,问十次保安,他轮流给你报十个不同宿舍楼。缺点很致命:DNS 有缓存(§ 4.2 讲过 TTL),服务器挂了不能立刻让全世界知道——所以它只能算"入门级负载均衡",正经网站还是会把 LB 放在 DNS 后面。

记住:硬件、软件、云,只是同一个"分单员"的三种扮相——背后的原理(门面、算法、健康检查)完全一样。你学会的是原理,具体选哪款,看预算、看规模、看运维能力。

现实场景:网站集群、CDN,还有你家

现在把视野拉回真实世界,看负载均衡都出现在哪里。

第一站:网站集群。大型网站从来不是"一台服务器",而是一大群。回指 § 4.5 那张请求链路图:"一个请求要过 CDN → 负载均衡 → 网关 → 应用 → 数据库好几道手"——现在你认识其中每一个角色了。负载均衡就站在"网关"前面,把海量请求分给后面一队应用服务器。大促之前,运维把几十台新服务器接进集群,负载均衡的健康检查自动发现"新窗口开业",开始往它们那儿派活——整个过程用户毫无感觉。这就是水平扩展最迷人的地方:加机器 = 加窗口,分单员自动认识它们。

第二站:CDN 边缘节点。回指 § 1.6 讲过的时延与带宽:内容离用户越远,时延越大。CDN 的干法是把内容缓存到全国各地的边缘节点上,让用户就近取货。但每个边缘节点本身也是一群缓存服务器——用户被调度到哪个节点、节点内的哪台服务器,背后又是一层负载均衡,只不过衡量的维度多了一个"距离"。CDN 解决"内容离你远不远",负载均衡解决"服务器忙不忙",两者配合:命中缓存的请求到不了源站(§ 4.5 讲过),没命中的请求回源时,源站前面照样站着 LB。

这里顺带交代一下负载均衡在机房里的位置关系它通常站在防火墙(回指 § 5.4)的后面。防火墙管"谁能进"——先把不怀好意的流量挡在门外;负载均衡管"进来了去哪"——把合法的请求分给后端的服务器。要是顺序反了,让 LB 直接暴露在公网入口,攻击流量会把它的算力耗尽,合法的用户反而被挤出去。标准架构是:公网 → 防火墙 → 负载均衡 → 应用服务器。这也正好串起第 5 章的四个角色:防火墙管门、负载均衡管分配、交换机管局域网内、路由器管跨网。

第三站:你家。坦白讲,家用场景基本用不到负载均衡。家里一般就一台出口路由器(§ 5.2 讲过那台"五合一"盒子),后面没有"一堆服务器"要分派。唯一沾点边的:双 WAN 路由器(同时接两条宽带,比如一条电信一条移动,让不同设备分流出口)——那是"出口分流",算家用版的最简负载均衡,但绝大多数家庭用不上。换句话说:负载均衡是"服务器多了之后必然出现的角色"——只要你有一台以上对外提供相同服务的机器,就总得有个东西站在前面分派。

还有一个值得知道的工程细节:负载均衡器自己也会成为瓶颈,所以生产环境通常是"两台 LB 互备"。一台挂了,另一台通过"虚拟 IP 漂移"接管同一个地址(这就是术语表里那个"故障转移 Failover")。就好比奶茶店门口摆了两个分单员,一个中暑了,另一个立刻接替他喊号。

常见误区:关于负载均衡的五个误解

负载均衡是"听起来很简单、用起来全是坑"的典型。五个流传最广的误解,一次拆干净——每一个都能用这一节前面讲过的原理回答。

五个误解背后其实是一个共同点:把"调度"这个角色的能力,安到了"算力"或"带宽"头上。分清"谁负责什么",误解自然不攻自破。

最后,把第 5 章的五个角色摆在一起收官。这一节是第 5 章"网络设备"的最后一节,五个角色正好拼出一个数据包从你家到网站的完整故事:

五个人各管一段、互不抢活——这本身就是 § 2.1/§ 2.2 分层思想的胜利:每一层只解决自己的问题,合起来解决整件事。下一章开始,网络篇将剪断网线进入无线世界:WiFi、蓝牙、4G/5G、卫星互联网——那是第 6 章《无线与移动》的主角。

Recap · 收束

一句话总结:负载均衡器是"奶茶店门口的分单员"——它站在一群后端服务器前面,对外只亮一个门面(虚拟 IP),对内按一套规则把请求分给不同的服务器,并定期确认每台后端还活着。谁也别闲着、谁也别累趴。

机制上记住五件事
· 为什么需要它:一台服务器扛不住海量请求(回指 § 4.5),水平扩展出多台服务器之后,总得有个"分单员"站在前面。
· 四层 vs 七层:L4 只看 IP+端口(叫号机只看号),L7 拆开 HTTP 看内容(分诊台听你要办什么事)。HTTP 本身的规范是 RFC 9110
· 五种分发算法:轮询(挨个叫号)、加权轮询(老手多接)、最少连接(谁闲给谁)、IP 哈希(同一人总去同一窗口)、一致性哈希(加减机器影响最小)。其中一致性哈希是工程实践概念,没有对应的 RFC
· 健康检查:主动探测(LB 定时发请求问"你还活着吗")或被动心跳(后端自己举手报到),挂了就摘除、修好再放回。
· 会话保持:sticky session 把同一用户永远粘到同一台(有单点风险);现代做法是共享会话存储,或干脆无状态、把状态写进 Cookie(回指 § 4.5)。

第 5 章到此收官:交换机(§ 5.1)管同一条街、路由器(§ 5.2)管城际干线、网关与光猫(§ 5.3)管家门口那道门、防火墙(§ 5.4)管谁能进门、负载均衡(§ 5.5)管进门之后去哪个窗口——五个角色各管一段,互不抢活。

下一步:网络篇要进入无线世界了——下一章《无线与移动》讲 WiFi、蓝牙、4G/5G 和卫星互联网;第一节《WiFi 原理》已经上线,点击右下角就能接上:那是切断电缆后的自由。

☰ 主页
Xue Hai Wu Ya · Network · § 5.5 · 负载均衡 LB