午间十二点,大学食堂人声鼎沸。新来的张经理发现一个棘手问题:招牌铁板饭窗口排起三十米长队,隔壁牛肉面窗口却门可罗雀。如果他把学生平均分流到每个窗口,铁板饭师傅忙不过来;如果全凭学生自己选,总有人吃不上饭。最后张经理在食堂装了叫号屏,提前统计各窗口排队人数,动态把订单派给最空闲的师傅,还定期检查哪个窗口临时关门,让老顾客优先去熟悉的窗口——这个“叫号屏”,就是计算机世界里的负载均衡器。负载均衡把海量请求像分派学生一样分发到多台服务器,通过轮询、加权、最少连接等算法决定每个请求该找哪位“师傅”,再配合四层/七层分流、健康检查和会话保持策略,让整个系统既跑得快又不容易瘫痪。这篇文章带你从头学会这套“食堂管理术”。

岗位关联

对 AI 从业者来说,负载均衡是高并发系统设计的底层功夫。掌握它,你就知道服务能扛多大流量、如何在局部故障时稳如泰山,这是架构师和运维工程师的核心竞争力。

目录
  1. 可视化演示
  2. 负载均衡原理
  3. 轮询与加权轮询
  4. 最少连接与哈希算法
  5. 四层与七层负载均衡
  6. 三大开源工具对比
  7. 健康检查机制
  8. 会话保持策略
  9. 架构选型实战
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

负载均衡调度算法流量分发 轮询算法按顺序均匀分配请求到各服务器,实现简单但不考虑性能差异 加权轮询按服务器权重分配请求,性能强的服务器承担更多流量 最少连接优先分配给当前连接数最少的服务器,动态适应实际负载 target = argmin(connᵢ) 不同调度算法在公平性和效率间各有取舍

负载均衡原理

张经理的叫号屏解决的核心问题是什么?不是把学生平均分到窗口,而是确保每个窗口都被高效利用,让食堂整体出餐量最大。没有叫号屏时,某个窗口挤爆、某个窗口闲置,总出餐量上不去。计算机系统也是一样:单台服务器性能有天花板,把请求集中打到一台机器,它就会像超载的铁板饭窗口一样“罢工”。

负载均衡器就是这个叫号屏。它位于客户端和后端服务器集群之间,接住所有请求,再按一定策略转发到某一台后端服务器。后端集群对外只暴露一个虚拟 IP(VIP),客户端完全感知不到背后有多少台机器,这就是“流量分发”的本质——对内多台分担,对外一个入口。负载均衡器扮演的是“总调度员”角色,所有请求先经过它,再由它决定谁接单。

有了负载均衡,系统获得两个核心收益:一是横向扩展能力,食堂不够用就多开窗口,服务器不够用就加机器,无需改动代码;二是高可用能力,某台服务器宕机时,负载均衡器把它剔除,请求自动落到其他机器,整个过程用户无感。用概率的眼光看问题:单机可用性为 a,n 台机器并联后,只要至少一台活着系统就能服务,整体可用性大幅提升。这就是负载均衡成为高可用系统核心组件的原因。

张经理发现,叫号屏不能只是“平均分”,还要知道哪个窗口最空、哪个窗口快打烊,否则形同虚设。负载均衡器同样如此——它的灵魂在于“算法”。接下来几节,我们看看食堂经理的各种分派策略。

A=1−(1−a)n\displaystyle A = 1 - (1 - a)^n
单台机器可用性 99%,两台并联后整体可用性变成 99.99%。负载均衡让“多台机器”变成一个更可靠的“超级机器”。
  1. 单机可用性 a单台服务器在一年内正常服务的时间占比,比如 99% 表示一年约 3.65 天可能故障。
    a=0.99a = 0.99
  2. 单台故障概率一台机器挂掉的概率是 1 减去它的可用性,这是“出问题”的度量。
    1−a1 - a
  3. 联合故障概率n 台机器同时挂掉的概率,因为每台独立故障,所以相乘。
    (1−a)n(1 - a)^n
  4. 整体可用性用 1 减去“全部挂掉”的概率,得到“至少有一台存活”的概率。
    A=1−(1−a)nA = 1 - (1 - a)^n

轮询与加权轮询

张经理最开始用最简单的方式:叫号屏按 1、2、3……顺序把订单轮流派给每个窗口。这就是“轮询”(Round Robin),请求按顺序轮流分发到每一台后端服务器,大家机会均等。新同学来食堂,最爱这种“人人有份”的公平感。

但轮询有个问题:铁板饭窗口师傅三头六臂效率高,牛肉面窗口新人手脚慢,轮流派单导致快的窗口排队、慢的窗口积压。于是张经理给窗口标了“产能分”:铁板饭 5 分、牛肉面 3 分、饺子 2 分,按 5:3:2 的比例派单。这就是加权轮询(Weighted Round Robin),权重越大,分到的请求越多。权重通常根据服务器的 CPU 核数、内存大小等配置设定。

加权轮询用权重描述机器的处理能力,适合后端配置不一的场景。权重为 $w_i$ 的机器 i 分到的请求比例,等于它的权重占所有机器权重之和的比例。不过经典的加权轮询在权重相差大时,会出现“前面全是重机器、后面全是轻机器”的忽高忽低现象。Nginx 采用的平滑加权轮询通过动态调整当前权重,让请求序列像波浪一样均匀交错,避免短时间内的流量毛刺。

张经理满意之余也发现,光看窗口的“产能分”还不够——如果某窗口前面已经排了 20 个人,师傅再快也应付不过来。派单,还得看看窗口前的队伍长度。这就引出了下一节。

Pi=wi∑j=1nwj\displaystyle P_i = \frac{w_i}{\sum_{j=1}^{n} w_j}
铁板饭窗口“产能分”5 分、牛肉面 3 分、饺子 2 分,那么每 10 个订单里大约有 5 个给铁板饭、3 个给牛肉面、2 个给饺子。
  1. 第 i 台机器的权重$w_i$ 表示服务器 i 的处理能力评分,配置越高权重越大。
    wi=5w_i = 5
  2. 所有权重求和$\sum_{j=1}^{n} w_j$ 把 n 台服务器的权重全部加起来,得到权重总量。
    ∑j=1nwj=5+3+2=10\sum_{j=1}^{n} w_j = 5 + 3 + 2 = 10
  3. 请求分配比例第 i 台机器分到的请求比例等于它的权重除以总权重。
    Pi=510=0.5P_i = \frac{5}{10} = 0.5

最少连接与哈希算法

张经理让叫号屏每次派单前先扫一眼各窗口的排队人数,哪个队伍最短就把订单派给哪个。这就是“最少连接”(Least Connections):请求到达时,负载均衡器统计每台后端服务器当前的活跃连接数,把新请求分给连接数最少的那台。

最少连接比轮询更贴近“真实负载”,因为连接数是动态的:一台慢服务器即使权重低,只要它当前接的请求少,新请求也可以优先给它。实际中常把权重和连接数结合,形成加权最少连接。公式上,最少连接选择的是所有候选中活跃连接数 $C_i$ 最小的服务器 $i^*$,这个“argmin“符号就是”从一堆候选里挑出最小的那个”的动作。

张经理还遇到一个诉求:有些同学认准了铁板饭的阿姨,希望每次都在同一个窗口。计算机里用户也有类似需求——登录状态、购物车数据如果散落到不同服务器,每次都要重新认证。IP 哈希算法对客户端 IP 做哈希后取模,把来自同一 IP 的请求始终映射到同一台后端,实现了天然会话亲和。但节点增删时普通取模会大范围失效,一致性哈希把节点映射到环形空间,增删节点只影响相邻区域,适合缓存类场景。

现在张经理的工具箱里有轮询、加权、最少连接、哈希四大算法,但他还有更根本的问题没解决:叫号屏该装在大门口(只看学生来不来),还是装在窗口内部(看清盘子里是什么菜)?这就是负载均衡的“层”的问题。

i∗=arg⁡min⁡i=1..nCi\displaystyle i^* = \arg\min_{i=1..n} C_i
就像站在食堂门口看一眼哪条队伍最短就派你去哪,最少连接算法每次选择当前“最闲”的那台服务器。
  1. 活跃连接数$C_i$ 表示第 i 台后端服务器当前正在处理的请求数量。
    Ci={12,5,8}C_i = \{12, 5, 8\}
  2. 最小化操作argmin 表示“找到使 $C_i$ 最小的那个下标”,是所有候选中的最小值位置。
    arg⁡min⁡iCi=2\arg\min_i C_i = 2
  3. 选中目标$i^*$ 是最终被选中的服务器序号,新请求将转发给它。
    i∗=2i^* = 2

四层与七层负载均衡

食堂叫号系统有两种设计。省事版:大门口放一个发号机,只数人头发号,不关注学生点了什么菜,学生进了食堂自己绕到对应窗口。升级版:叫号屏能看清每个订单点了什么菜,直接告诉学生“铁板饭去 3 号窗口、牛肉面去 5 号窗口”。这两种设计,对应负载均衡的“四层”与“七层”。

四层负载均衡工作在传输层,负载均衡器只解析 TCP/UDP 报文头部的 IP 和端口,做地址转发(比如 LVS、HAProxy 的 TCP 模式)。它不关心报文内容,转发速度极快,像只数人头的发号机;七层负载均衡工作在应用层,解析 HTTP 报文中的 URL、Header、Cookie 等内容后按规则转发(比如 Nginx),像看得懂菜单的引导员。

四层和七层的时延差异可以用一个简单公式表达:七层时延约等于四层时延加上报文解析开销。别看只是多了解析,在高并发下这个差距会被放大:四层每秒可处理百万级连接,七层在十万到几十万量级,同时七层能做 URL 路由、限流、灰度发布等高级功能。选择依据是:追求极致性能且转发逻辑简单选四层,需要精细化路由和管理选七层,生产环境往往两者叠加使用。

张经理想通了:发号机适合大食堂低成本管控,看得懂菜单的引导员适合讲究服务的食堂。但无论选哪种,他还得选“设备商”——找谁来当这个叫号屏?市面上最出名的三个“叫号屏”厂家就是 LVS、Nginx 和 HAProxy。

T7L≈T4L+Tparse\displaystyle T_{7L} \approx T_{4L} + T_{parse}
引导员比发号机多做的“看菜单”动作,就是七层比四层多出的解析开销。看得越细,花的时间越多。
  1. 四层转发耗时$T_{4L}$ 是负载均衡器只改目标地址、不碰报文内容所需的时间。
    T4L=0.1 msT_{4L} = 0.1\,ms
  2. 解析开销$T_{parse}$ 是解析 HTTP 头、URL 等应用层信息额外消耗的时间。
    Tparse=0.5 msT_{parse} = 0.5\,ms
  3. 总耗时$T_{7L}$ 约等于两者之和,体现了七层负载的额外成本。
    T7L≈0.1+0.5=0.6 msT_{7L} \approx 0.1 + 0.5 = 0.6\,ms

三大开源工具对比

张经理在展会上看中三款叫号屏:LVS 像一台内核级的高速发号机,Nginx 像一个懂菜单的引导员,HAProxy 像一个极其专注的专职调度员。三者并不完全同类,但都是负载均衡领域的明星,各有绝活。

LVS(Linux Virtual Server)运行在 Linux 内核态,通过修改数据包的目标地址做四层转发,支持 DR、NAT、TUN 三种模式,性能最强,单机可支撑百万级并发,适合作为集群最前端;HAProxy 是用户态专业的负载均衡软件,四层七层都支持,配置灵活、统计报表强大,尤其擅长 TCP 会话管理和健康检查;Nginx 本身是高性能 Web 服务器,其负载均衡模块按 URL 等七层信息转发,还能兼任静态资源服务和限流。

三者的吞吐能力大致满足下面的不等式:相同硬件下,LVS 的转发吞吐最高,HAProxy 次之,Nginx 七层转发再次。选型口诀:需要极致性能、扛最外层流量选 LVS;需要专业的四层/七层混合调度和精细化健康检查选 HAProxy;需要 Web 服务、反向代理、负载均衡一体化选 Nginx。实际大厂常把 LVS 挡在最前,Nginx 做七层路由,形成分层负载。

叫号屏装上后,张经理又发现新问题:某个窗口的师傅突然请假,叫号屏却还在拼命派单,订单越积越多。他意识到,叫号屏必须随时知道每个窗口是不是真的在营业。

TLVS≥THAProxy≫TNginx\displaystyle T_{LVS} \ge T_{HAProxy} \gg T_{Nginx}
发号机(LVS)只做一件事所以最快,引导员(Nginx)要认菜单所以最慢,专职调度员(HAProxy)则介于两者之间。
  1. LVS 吞吐$T_{LVS}$ 表示 LVS 在内核态转发的每秒请求处理量,量级可达百万级。
    TLVS≈106T_{LVS} \approx 10^6
  2. HAProxy 吞吐$T_{HAProxy}$ 是用户态事件驱动模型的吞吐,通常为几十万 QPS。
    THAProxy≈5×105T_{HAProxy} \approx 5 \times 10^5
  3. Nginx 吞吐$T_{Nginx}$ 因涉及 HTTP 解析,同硬件下通常落在十万级。
    TNginx≈1×105T_{Nginx} \approx 1 \times 10^5

健康检查机制

张经理给叫号屏加了一个功能:每 5 秒“拍一拍”每个窗口,问一句“师傅在吗?”。如果连续 3 次没有回应,就把该窗口标记为“暂停营业”,不再派单;恢复后自动重新开放。这个机制在负载均衡里叫“健康检查”。

健康检查分主动与被动:主动探测是负载均衡器按固定周期向后端发送探测请求,比如 ICMP ping 检查主机是否存活、TCP 检查端口能否建立连接、HTTP 检查业务接口是否返回 200;被动熔断是负载均衡器观察真实转发中连续失败的次数,达到阈值就自动摘除,相当于“窗口连续出餐失败三次自动暂停”。

判定规则可以抽象为状态机:连续成功 $s_{ok}$ 次达到上线阈值 $u$ 才标记为 up,连续失败 $s_{fail}$ 次达到下线阈值 $f$ 才标记为 down。两个阈值防止抖动——网络抖动一次就摘除会导致雪崩,检查太频繁又会增加后端负担。此外还有优雅摘除:让正在处理的请求先完成(排空 drain),再下线新流量,避免用户请求被硬生生切断。

健康检查保证了“活着的窗口才接单”,但还有一个体验问题:老顾客希望每次都去熟悉的窗口,可轮询和最少连接会把他分到任意窗口。张经理该怎么满足这群“认窗口”的同学?

s={up,sok≥udown,sfail≥f\displaystyle s = \begin{cases} up, & s_{ok} \ge u \\ down, & s_{fail} \ge f \end{cases}
窗口连续三次出餐失败就暂停接单,连续三次正常回应才重新开张——健康检查就是这套“停业/复业”规则。
  1. 成功计数$s_{ok}$ 是连续健康探测成功的次数,每次成功加一。
    sok=3s_{ok} = 3
  2. 上线阈值$u$ 是标记为健康所需的最少连续成功次数,防止一次成功就误判。
    u=3u = 3
  3. 失败计数$s_{fail}$ 是连续探测失败的次数,每次失败加一。
    sfail=3s_{fail} = 3
  4. 下线阈值$f$ 是判定为故障并摘除所需的最少连续失败次数,防止瞬间抖动误伤。
    f=3f = 3

会话保持策略

张经理发现,有些同学打饭时喜欢和阿姨聊两句,每次换窗口就得重新解释一遍口味。于是叫号屏推出“老顾客模式”:识别出同一张饭卡,就始终把它派到上次的窗口。计算机系统中这叫“会话保持”(Session Stickiness),确保同一用户的多个请求落在同一台后端服务器,避免登录态丢失、购物车清空。

会话保持的实现方式主要有三种:一是会话粘滞,负载均衡器按用户会话 id 哈希到固定后端,最简单但节点增删会引起重映射;二是 Cookie 植入,七层负载均衡器在后端返回的响应中植入一个包含后端标识的 Cookie,后续请求带着 Cookie 直接路由到对应服务器,灵活且精准;三是分布式会话,把会话数据抽到 Redis 等共享存储,此时后端无状态,任意机器都能服务,是最彻底的解法。

一致性哈希在会话保持中也很常用:把服务器节点映射到哈希环上,请求 key 沿环顺时针找到最近的节点。相比普通取模,增删节点时只有环上相邻区域的请求会迁移,其他用户的会话不受影响,因此特别适合缓存和长连接场景。公式里 $pos(x)$ 表示把 key 或节点映射到环上 0 到 $2^{32}-1$ 的位置,ring_next 表示顺时针查找的行为。

至此,张经理把叫号屏的算法、层级、设备、体检、认人机制都备齐了。但每套食堂的规模、预算、客流特点都不同,怎么组合这些零件才是终极大考——这就是架构选型。

server=ring_next(h(key) mod 232)\displaystyle server = ring\_next(h(key) \bmod 2^{32})
每个窗口把“老顾客”记在小本本上,新顾客来了就问一句话,然后把他带到对应窗口——哈希环就是这张记满顾客的环形小本本。
  1. 哈希映射$h(key)$ 把用户的会话 key 打散成一个随机数。
    h(key)=29384756h(key) = 29384756
  2. 环上位置对 $2^{32}$ 取模,把哈希值落在一个固定大小的环上。
    pos=29384756 mod 232pos = 29384756 \bmod 2^{32}
  3. 顺时针查找$ring\_next$ 表示从该位置出发,沿环找到的第一个服务器节点。
    server=ring_next(pos)server = ring\_next(pos)

架构选型实战

张经理发现,隔壁小面馆只有两个窗口,根本不需要叫号屏;而五星级酒店食堂要兼顾 VIP 包间和千人快餐厅。架构选型的第一原则是“看菜下饭”:系统规模不同,负载均衡方案天差地别。

选型的三个核心步骤:先做场景分析——业务是长连接还是短连接?读写比例如何?要求秒级容灾还是分钟级?再做容量规划——估算峰值 QPS、平均请求体大小和单机承载能力,算出最少需要多少台后端机器;最后定高可用拓扑——负载均衡器自身也要冗余,通常采用主备(keepalived 做 VIP 漂移)或集群模式,避免“叫号屏坏了全食堂瘫痪”。

容量规划的经典公式是:所需机器数 N 等于峰值 QPS 除以单机可承载 QPS 后向上取整。单机承载能力要通过压测获得,而不是拍脑袋。典型的生产架构是多层叠加:DNS 轮询做地域分流,LVS 在最前扛四层流量,Nginx 做七层路由、限流和静态缓存,微服务层再用注册中心做客户端负载均衡,每层各司其职又互相兜底。

张经理最终按食堂规模定制了方案,叫号屏每天稳定运转,铁板饭窗口不再排队,牛肉面师傅也忙得过来。选型没有银弹,只有结合业务特征、性能预算和团队运维能力做权衡。记住那句老话:没有最好的负载均衡,只有最合适的负载均衡。

N=⌈QPSpeakQPSsingle⌉\displaystyle N = \left\lceil \frac{QPS_{peak}}{QPS_{single}} \right\rceil
就像张经理先数食堂每天最多来多少学生、再算每个窗口一小时能出多少份餐,一除就知道该开几个窗口,还得留出余量应付突发客流。
  1. 峰值吞吐$QPS_{peak}$ 是业务高峰期每秒最大请求数,通常按大促或双十一峰值预估。
    QPSpeak=100000QPS_{peak} = 100000
  2. 单机容量$QPS_{single}$ 是单台服务器通过压测得到的每秒可处理请求数。
    QPSsingle=20000QPS_{single} = 20000
  3. 向上取整$\lceil \cdot \rceil$ 表示结果向上取整,保证机器数只多不少。
    N=⌈10000020000⌉=5N = \left\lceil \frac{100000}{20000} \right\rceil = 5

AI 应用场景

秒杀大促的流量入口设计

阶段:高并发系统架构设计

解决的问题:传统 DNS 轮询只做域名解析,不感知后端故障和负载;突增流量瞬间击垮单点服务。运用正文讲的分层思想,用 LVS 做四层入口扛住百万级连接,Nginx 做七层路由和限流,配合健康检查自动剔除异常节点,像张经理在食堂门口加分流、在窗口前加引导,让每个订单都有窗口接。

具体案例:某电商双十一大促,入口 DNS 按地域分流到四个机房,每个机房前置一对 LVS(keepalived 主备),后面挂 8 台 Nginx 做七层转发和限流,Nginx 下游是 200 台应用服务器按加权轮询分发。最终扛住数十万 QPS 峰值,单机故障时自动摘除,用户无感知。

微服务调用链的客户端负载均衡

阶段:服务治理

解决的问题:集中式负载均衡让所有调用都经过 LB,多一跳网络延迟且 LB 本身成为瓶颈。改用“客户端负载均衡”:注册中心下发实例列表,客户端自己按算法选一台,类似学生自己看窗口排队情况选窗口。这样去中心化,性能更好、扩展更灵活。

具体案例:订单服务调用用户服务,注册中心返回 8 个实例及各自权重,客户端使用平滑加权轮询选实例,配合超时重试和熔断降级。某实例连续调用失败时,客户端主动将它标记为不健康并切换,避免故障扩散。

Python 演示

python33 行
# 平滑加权轮询负载均衡器示例import time class SmoothWeightedRoundRobin:    def __init__(self, servers):        # servers 形如 [{'name': 'backend-a', 'weight': 5}, ...]        self.servers = servers        self.current = [0] * len(servers)     def next(self):        total = 0        best = -1        for i, s in enumerate(self.servers):            self.current[i] += s['weight']            total += s['weight']            if best == -1 or self.current[i] > self.current[best]:                best = i        self.current[best] -= total        return self.servers[best]['name'] def main():    servers = [        {'name': 'backend-a', 'weight': 5},        {'name': 'backend-b', 'weight': 3},        {'name': 'backend-c', 'weight': 2},    ]    lb = SmoothWeightedRoundRobin(servers)    for _ in range(20):        print(lb.next())        time.sleep(0.05) if __name__ == '__main__':    main()
目的:用 Python 实现 Nginx 采用的平滑加权轮询算法,演示权重 5:3:2 的三台后端在连续 20 次请求中如何被均匀又不抖动地选中。
  1. self.current[i] += s['weight']每轮先给每个候选者加上权重分,模拟“不同产能窗口的累积机会”。
  2. total += s['weight']累加所有权重,在选出后用于扣减,保证长期比例准确。
  3. if best == -1 or self.current[i] > self.current[best]遍历选出当前分数最高的那个后端,即“本轮最该接单的窗口”。
  4. self.current[best] -= total被选中的选手扣掉总权重分,让它的分数降下来,下次不会连续被选。
  5. for _ in range(20)模拟连续到达的 20 个请求,观察分发序列。

常见误区

误区我刚开始学负载均衡时觉得,它就是把请求 1234 轮流分给服务器,只要每台机器分到的请求数量差不多,就万事大吉了。

正解轮询只是最简单的静态算法,它完全不看服务器配置差异和实时负载。就像食堂经理不管窗口前排队多长都硬派单,慢窗口迟早积压崩溃。生产环境更常用加权轮询、最少连接或哈希,因为后端机器配置往往参差不齐,请求耗时也有长有短,均匀不等于均衡。

为何常见:入门教材和示意图几乎都用轮询举例,加上“负载均衡”字面带有“平均分布”的暗示,很容易让人以为均匀分发就是全部。

误区四层负载均衡性能比七层高一个量级,那我所有场景都用四层不就好了吗?反正都是把请求转到后端。

正解四层再快,也做不了 URL 路由、Cookie 会话保持、灰度发布这些七层专属能力。就像发号机再快,也没法告诉学生“铁板饭去 3 号窗口”。真实系统中二者是互补关系:LVS 四层扛流量,Nginx 七层做精细化路由,各司其职。迷信某一层而拒绝另一层,等于放弃了系统设计的一半武器。

为何常见:性能数字最容易给人留下印象,初学者容易把“快”等同于“好”,忽略了业务功能需求。

误区健康检查不就是负载均衡器每隔几秒发个 ping 包,能通就说明服务器活着吗?那只要服务器没断电就永远不会摘除。

正解ping 只能证明主机活着,服务进程可能已经僵死、端口可能拒绝连接、业务接口可能返回 500。真正的健康检查分三层:ICMP 查主机、TCP 查端口、HTTP 查业务状态码,还可以自定义探测脚本检查磁盘、CPU 等资源水位。就像一个窗口“人还在”不代表“能出餐”,要真正确认菜品能端出来才算健康。

为何常见:很多人把网络连通性和服务可用性画等号,忽略了“进程活着”和“业务可用”之间的巨大差距。

误区会话保持让同一个用户总是打到同一台服务器,那其他机器不就闲着了?这和负载均衡“分散流量”的初衷不是矛盾吗?干脆关掉最公平。

正解购物车、登录态、上传进度这类场景天然要求“同一客户认同一窗口”。硬要关掉会话保持,用户每次刷新都被分到不同机器,登录态反复丢失,体验直接崩溃。真正优雅的解法是“分布式会话”:把会话数据放到 Redis 共享存储,后端全部无状态,既保留负载均衡的自由调度,又保住用户体验。

为何常见:初学者把“分散”理解为唯一目标,忽略了业务的连续状态需求,没意识到“状态外置”可以同时满足两边。

面试题

Q1. 轮询调度算法的主要缺点是?

单选题 · easy

  • A.无法感知服务器真实负载← 正确答案
  • B.部署起来太复杂
  • C.需要额外付费购买
  • D.只支持两台服务器

答案:A。轮询像食堂经理按固定顺序安排学生打饭,完全不看哪个窗口快哪个慢。后端服务器配置不同、当前负载不同时,轮询会照单全收导致劣配机器过载。B/C/D 均与轮询算法本身无关。

Q2. 下列哪种负载均衡基于七层工作?

单选题 · easy

  • A.LVS 的 DR 模式
  • B.Nginx 按 URL 路径转发← 正确答案
  • C.硬件交换机根据 MAC 转发
  • D.HAProxy 的 TCP 模式

答案:B。Nginx 按 URL 路径转发需要解析 HTTP 报文,是典型七层负载均衡,相当于“看得懂菜单的引导员”。LVS 的 DR 模式、硬件交换机 MAC 转发、HAProxy 的 TCP 模式都只处理到传输层及以下。

Q3. 加权轮询中两台机器权重比为 2:1,长期运行后表现如何?

单选题 · mid

  • A.两台机器严格轮流一次
  • B.高权重机器分到的请求数是低权重的两倍← 正确答案
  • C.低权重机器永远收不到请求
  • D.两台机器随机接收请求

答案:B。加权轮询按权重比例分配请求,权重大窗口分到的学生多。它不是严格交替,而是统计上接近 2:1。A 是普通轮询的特征,C 是权重设为 0 的行为,D 是随机算法的特征。

Q4. IP 哈希负载均衡最适合的场景是?

单选题 · mid

  • A.需要临时扩展缓存集群
  • B.希望同一用户始终访问同一台后端← 正确答案
  • C.后端服务器性能差异极大
  • D.要求压测流量绝对均匀

答案:B。IP 哈希把同一客户端 IP 映射到同一台服务器,天然实现会话亲和,像老顾客固定熟悉的窗口。A 扩容会导致哈希重映射,应选一致性哈希;C 应选加权算法;D 应选轮询。

Q5. 关于健康检查的主动探测,下列说法正确的是?

单选题 · mid

  • A.负载均衡器周期性向后端发探测请求← 正确答案
  • B.后端服务器主动上报故障
  • C.客户端发现超时后切换
  • D.运维人员手工重启后端

答案:A。主动探测是负载均衡器按固定间隔发起 ping、端口或 HTTP 探测,像经理定期去窗口问询“师傅在吗”。B 是代理上报的被动模式,C 是客户端容错,D 是运维动作,三者都不是主动探测。

Q6. 一致性哈希引入虚拟节点的主要目的是?

单选题 · hard

  • A.让哈希环上节点分布更均匀← 正确答案
  • B.提高哈希函数的计算速度
  • C.压缩哈希环的存储空间
  • D.让所有请求都命中同一节点

答案:A。真实节点落在环上的位置是随机的,节点少时容易扎堆,导致大量 key 顺时针归到同一个服务器。为每个节点生成多个虚拟副本分布全环,使归属更均匀。B/C/D 均不是虚拟节点的作用。

Q7. 最少连接算法如何选择目标服务器?

单选题 · easy

  • A.选当前活跃连接数最少的服务器← 正确答案
  • B.选 IP 地址最小的服务器
  • C.选 CPU 型号最新的服务器
  • D.按配置文件里的顺序选

答案:A。最少连接像选排队人最少的窗口,每次把新请求交给当前活跃连接数最少的后端。B/C/D 与算法定义无关。这种动态算法比轮询更贴近真实负载情况。

Q8. 下列哪些属于负载均衡常见的健康检查方式?

多选题 · mid

  • A.ICMP ping 探测← 正确答案
  • B.TCP 端口连通性探测← 正确答案
  • C.HTTP 状态码探测← 正确答案
  • D.修改后端源码重新部署

答案:ABC。ICMP 检查主机存活,TCP 检查服务端口是否监听,HTTP 检查业务接口是否返回 200,三者是主动探测的常用手段,层层递进验证“窗口还开着且能出餐”。D 是应用变更操作,不是健康检查。

Q9. 关于 LVS 的转发模式,下列说法正确的有?

多选题 · hard

  • A.NAT 模式会修改数据包的源目地址← 正确答案
  • B.DR 模式要求后端和负载均衡器在同一局域网← 正确答案
  • C.TUN 模式通过 IP 隧道封装转发← 正确答案
  • D.三种模式都需要修改后端应用代码

答案:ABC。NAT 做网络地址转换,DR 利用 MAC 改写且要求同一二层网络,TUN 用 IP-in-IP 隧道。三种模式对于后端应用都是透明的,无需修改代码,所以 D 错误。

Q10. 大型电商秒杀系统常用的分层负载均衡组合包含?

多选题 · extreme

  • A.DNS 轮询做地域级分流← 正确答案
  • B.LVS 做集群入口四层转发← 正确答案
  • C.Nginx 做七层路由和限流← 正确答案
  • D.服务注册中心做客户端负载均衡← 正确答案

答案:ABCD。大型系统通常 DNS 按地域分流到机房,LVS 扛入口四层流量,Nginx 做七层路由、限流和静态缓存,微服务层再用注册中心下发实例列表由客户端自选负载。四个层次各司其职又互相兜底,是秒杀架构的常见组合拳。