Skip to content

第 8 章 · 常见踩坑

生活类比:大堂经理也会犯错——把所有人都引到刚晕倒的柜台、一个窗口倒了大家挤爆另一个、重复给顾客结账两次……
这一章是 避坑手册,生产事故多半出在「以为 LB 万能」的细节里。


8.1 坑 1:重试导致重复操作(最危险)

场景

用户 POST /orders(下单)
  → LB 转发到 A
  → A 处理慢,LB 超时
  → LB 认为失败,重试到 B
  → B 又下一单
  → 用户账户扣了两次钱

Nginx 配置:

nginx
proxy_next_upstream error timeout http_502 http_503 http_504;

默认对 idempotent 方法(GET/HEAD)重试;POST 等 默认不重试——但前端、网关、客户端 SDK 可能各自重试。

对策

层级做法
业务幂等键 Idempotency-Key: uuid
数据库唯一约束 (user_id, order_no)
LB谨慎开启 POST 重试;调大 proxy_read_timeout
前端防重复提交按钮

生活例子:顾客刷卡没听到「滴」,又刷一次——POS 机要能识别「同一笔别扣两次」。


8.2 坑 2:健康检查误杀

症状

节点一会儿 healthy 一会儿 unhealthy(flapping),流量抖动。

常见原因

  • 探针 timeout 太短,GC 时偶尔超时
  • /healthz 走了鉴权,返回 401
  • /healthz 查了慢 SQL,探针本身太重
  • 网络抖动,threshold 设太小

对策

yaml
# 示例:连续 3 次失败才摘,连续 2 次成功才恢复
unhealthy_threshold: 3
healthy_threshold: 2
timeout: 3s

探针接口要 极轻ping DB 连接池,别 SELECT COUNT(*) 大表。


8.3 坑 3:会话丢失(IP Hash 依赖症)

见第 5 章。症状:用户随机掉登录。

根因:扩缩容、NAT、移动网络 IP 变化。
解法:Redis Session 或 JWT,放弃 IP Hash。


8.4 坑 4:慢启动(Slow Start)缺失

场景

新 Pod 刚启动,JVM 还在预热,立刻被打满流量 → 大量超时 → 又被健康检查杀掉 → 发布失败

对策

  • K8s readinessProbeinitialDelaySeconds
  • 网关 渐进加权:新节点 weight 从 1 渐增到 100
  • 应用层 warmup:启动后先预热缓存

生活例子:新实习生第一天,先让他旁观 2 小时,再慢慢接简单业务。


8.5 坑 5:热点机器(Hot Spot)

原因

  • IP Hash + 大客户 NAT IP
  • 一致性哈希虚拟节点不足
  • 某个「超级用户」请求量极大

现象

A: CPU 95%
B: CPU 20%
C: CPU 15%

对策

  • 换算法(轮询 / least_conn)
  • 一致性哈希加虚拟节点
  • 热点 key 拆分、本地缓存

8.6 坑 6:LB 自身成为单点

        [单台 Nginx]  ← 挂了全站下线
       /     |     \
    [A]    [B]    [C]

对策

  • 主备:Keepalived + VIP 漂移
  • 多实例:云 LB 天然多 AZ
  • DNS 多 A 记录 + 健康检查(次选)

8.7 坑 7:长连接未开启

每次请求新建 TCP → TLS 握手 → 后端延迟 +1~30ms。

三件套(Nginx):

nginx
upstream backend { keepalive 64; }
proxy_http_version 1.1;
proxy_set_header Connection "";

8.8 坑 8:超时配置不合理

配置过短配置过长
正常慢请求被断开僵死连接占满 worker
触发无谓重试用户等太久

P99 延迟 + 业务容忍度proxy_read_timeout,别拍脑袋。


8.9 坑 9:雪崩(Cascade Failure)

后端 A 变慢
  → LB 重试增多
  → 更多请求堆积
  → A 更慢
  → 健康检查超时
  → 流量涌向 B、C
  → B、C 也扛不住
  → 全挂

对策组合拳

  • 熔断:错误率超阈值暂停调用
  • 限流:入口控制 QPS
  • 超时:别无限等
  • 舱壁隔离:核心接口独立线程池
  • 降级:非核心功能先关

生活例子:一个收银台慢了,大家全挤过去,结果全堵死——应该暂时关闭该通道并限流。


8.10 坑 10:忽略 X-Forwarded-For 伪造

客户端可伪造 X-Forwarded-For。只有 可信的 LB 应追加该头,应用取 最左还是最右 要统一规范。

nginx
# LB 追加真实 IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

应用侧应信任 来自 LB 网段 的请求,解析时取 $remote_addr 或规范化的最后一跳。


8.11 踩坑速查表

症状可能原因第一反应
随机 502后端挂了 / 健康检查未摘流查后端池状态
重复下单重试 + 非幂等查幂等键、重试配置
发布后全 502readiness 未就绪查探针、预热
某台 CPU 100%热点 / ip_hash查算法与 key 分布
登录老掉Session 不共享上 Redis / JWT
延迟突然升高长连接未开 / 后端满查 keepalive、连接数

8.12 一句话总结

LB 不是魔法:重试要幂等、探针要轻、会话要共享、发布要预热、入口要限流——否则大堂经理会把店带沟里。

下一章 → 09 · 综合实战