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

验证与排错步骤(含命令与说明)#

  1. 确认当前负载策略与配置生效
sudo nginx -t
sudo systemctl reload nginx
# 预期:syntax is ok / test is successful
  1. 追踪请求路由,验证命中节点
curl -I -H "Cookie: SESSIONID=abc123" http://example.com
# 观察响应头是否包含上游标记(可在日志中加入 $upstream_addr)
  1. 日志定位热点与漂移

    追加日志格式到 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
  1. 模拟节点故障与健康检查效果
# 临时阻断 10.0.0.12 的 8080 端口
sudo iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.12 -j DROP

# 观察是否切走流量(结合日志与 upstream_response_time)
  1. 检查头部透传完整性
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. 练习 1:验证粘性是否生效
    - 操作:使用固定 SESSIONID 连续请求 10 次
    - 命令:
    bash for i in {1..10}; do curl -s -H "Cookie: SESSIONID=abc123" http://example.com/; done
    - 预期:日志中 upstream_addr 仅出现 1 个后端

  2. 练习 2:模拟节点故障切换
    - 操作:禁用一台后端端口,观察请求是否切走
    - 预期:该节点不再出现在 upstream_addr 中,错误率下降

  3. 练习 3:检查头部透传
    - 操作:发送带 X-Request-Id 的请求
    - 预期:应用日志与 Nginx 日志出现相同 Request-Id

核心检查清单#

  • 负载均衡算法与业务状态是否匹配
  • 粘性策略与 cookie 域/路径是否一致
  • 故障节点是否及时摘除
  • 各节点 QPS/RT 是否存在长尾或热点
  • 请求头部与 session 标识是否完整透传