7.7.5 负载均衡与会话保持的稳定性问题
负载均衡与会话保持的稳定性问题#
原理草图:负载均衡与会话保持链路#
常见症状与影响#
- 登录态丢失、购物车清空、表单重复提交
- 请求持续命中单一后端形成“热点”
- 负载不均衡、某台后端过载、响应时间陡增
- 节点切换后大量 4xx/5xx 或重定向异常
典型根因#
- 会话保持方式不一致:cookie/ip_hash/应用 session 不匹配
- 健康检查缺失或配置不当,故障节点未及时摘除
- 后端时间差、域名或路径不一致导致 cookie 失效
- 负载算法不适配业务:轮询/最少连接/一致性哈希选择错误
- 多层代理未透传关键头部或协议
环境准备与安装示例#
以 Debian/Ubuntu 为例,安装 Nginx 并启用服务
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
nginx -v
# 预期:输出 nginx 版本号
配置示例:会话保持与健康检查#
文件路径:
/etc/nginx/conf.d/lb.conf
upstream app_backend {
# 基于 cookie 粘性(第三方模块可用 sticky,原生用 hash)
hash $cookie_SESSIONID consistent;
server 10.0.0.11:8080 max_fails=3 fail_timeout=10s;
server 10.0.0.12:8080 max_fails=3 fail_timeout=10s;
server 10.0.0.13:8080 max_fails=3 fail_timeout=10s;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_backend;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Request-Id $request_id;
proxy_connect_timeout 3s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_502 http_503 http_504;
}
}
应用侧设置 Session Cookie 示例(需要保证 domain/path 一致):
Set-Cookie: SESSIONID=abc123; Path=/; Domain=example.com; HttpOnly; Secure
验证与排错步骤(含命令与说明)#
- 确认当前负载策略与配置生效
sudo nginx -t
sudo systemctl reload nginx
# 预期:syntax is ok / test is successful
- 追踪请求路由,验证命中节点
curl -I -H "Cookie: SESSIONID=abc123" http://example.com
# 观察响应头是否包含上游标记(可在日志中加入 $upstream_addr)
- 日志定位热点与漂移
追加日志格式到
nginx.conf
log_format lb '$remote_addr $request_id $cookie_SESSIONID '
'$upstream_addr $status $request_time $upstream_response_time';
access_log /var/log/nginx/lb_access.log lb;
tail -f /var/log/nginx/lb_access.log
# 预期:能看到同一 SESSIONID 是否稳定命中同一 upstream
- 模拟节点故障与健康检查效果
# 临时阻断 10.0.0.12 的 8080 端口
sudo iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.12 -j DROP
# 观察是否切走流量(结合日志与 upstream_response_time)
- 检查头部透传完整性
curl -I http://example.com -H "X-Request-Id: test-001"
# 预期:应用日志能看到 X-Request-Id
常用问题定位清单(含命令解释)#
- 会话保持失效:检查 cookie 域/路径/协议是否一致
bash curl -I http://example.com/login # 关注 Set-Cookie 是否含 Domain/Path/Secure - 负载不均:查看各后端 QPS/RT
bash awk '{print $4,$5}' /var/log/nginx/lb_access.log | sort | uniq -c # 统计 upstream_addr 分布 - 健康检查不生效:确认 fail_timeout/max_fails
bash grep -n "max_fails\|fail_timeout" /etc/nginx/conf.d/lb.conf - 多层代理头部丢失:检查 X-Forwarded-For
bash curl -I http://example.com # 应用侧应能看到真实来源 IP
稳定性优化实践(含示例)#
- 会话共享存储(Redis)
# 仅示意:应用侧将 session 存入 Redis
# 预期:关闭粘性也不丢登录态
- 灰度权重控制
upstream app_backend {
server 10.0.0.11:8080 weight=5;
server 10.0.0.12:8080 weight=5;
server 10.0.0.13:8080 weight=1; # 新节点先低权重
}
- 无状态化改造
- 将用户状态从本地内存迁移到 Redis/数据库
- 登录态只依赖 Token/JWT
练习题(含预期结果)#
-
练习 1:验证粘性是否生效
- 操作:使用固定 SESSIONID 连续请求 10 次
- 命令:
bash for i in {1..10}; do curl -s -H "Cookie: SESSIONID=abc123" http://example.com/; done
- 预期:日志中 upstream_addr 仅出现 1 个后端 -
练习 2:模拟节点故障切换
- 操作:禁用一台后端端口,观察请求是否切走
- 预期:该节点不再出现在 upstream_addr 中,错误率下降 -
练习 3:检查头部透传
- 操作:发送带 X-Request-Id 的请求
- 预期:应用日志与 Nginx 日志出现相同 Request-Id
核心检查清单#
- 负载均衡算法与业务状态是否匹配
- 粘性策略与 cookie 域/路径是否一致
- 故障节点是否及时摘除
- 各节点 QPS/RT 是否存在长尾或热点
- 请求头部与 session 标识是否完整透传