主备切换时会话不丢失需同时解决nginx高可用与后端会话共享:一、用keepalived实现vip秒级漂移并监控nginx进程;二、后端统一用redis存session或启用consistent hash $cookie_jsessionid;三、配置健康检查与快速失败机制;四、完整验证vip切换、后端宕机等真实故障场景。

主备切换时会话不丢失,不能只靠 Nginx 自身的负载均衡配置,必须把“Nginx 高可用”和“后端会话保持/共享”两层问题同时解决。单靠 VIP 切换或 ip_hash 都无法真正保障——前者只管流量接管,后者在主备切换后因 upstream 成员变化会彻底打乱哈希映射。
一、先确保 Nginx 主备本身高可用且无感知切换
这是前提:客户端访问的是同一个 VIP(如 192.168.1.200),主节点宕机后,VIP 必须在 3–5 秒内漂移到备用节点,且 Nginx 进程已就绪。
- 两台 Nginx 服务器安装 keepalived,配置完全一致的 virtual_router_id 和 auth_pass
- 主节点设
state MASTER、priority 101;备节点设state BACKUP、priority 99 - 必须加入
vrrp_script检查 Nginx 进程存活(例如killall -0 nginx),失败时自动降权(如weight -2),避免“系统活着但 Nginx 挂了却不切换”的陷阱 - 确认网卡名(如 ens160)、防火墙放行 VRRP 组播(协议号 112)
二、后端服务层必须支持会话延续,而非依赖 Nginx 路由绑定
主备 Nginx 切换后,新请求会打到新主节点,它内部的 upstream 成员没变,但若用 ip_hash 或 sticky cookie,只要 upstream 列表发生变更(比如某台后端临时 down 掉),哈希结果就会整体偏移,用户 session 就断了。
- 首选方案:后端统一使用 Redis 存储 Session(如 Spring Session + Redis、PHP redis session handler、Node.js connect-redis)。所有后端实例读写同一份 session 数据,Nginx 可回归最简单的轮询或 least_conn,完全解耦
- 若无法改造后端,可启用
hash $cookie_JSESSIONID consistent;(原生支持,无需模块)。相比 ip_hash,它基于应用返回的会话 Cookie 哈希,不受 IP 变更、NAT、代理影响,且一致性哈希能最大限度减少后端增减时的会话漂移 - 禁用
ip_hash用于主备场景——它与 backup 节点互斥,且主备切换前后 Nginx 实例不同,哈希空间不连续,必然导致大量用户重登录
三、Nginx 配置需配合健康检查与快速失败机制
即使后端用了 Redis,也要防止请求被发往已故障的节点,造成超时或错误响应,间接引发客户端重试/刷新,破坏会话连续性。
- upstream 中为每个 server 设置
max_fails=2 fail_timeout=10s,让 Nginx 快速摘除异常节点 - location 中启用
proxy_next_upstream error timeout http_502 http_503 http_504,遇到这些错误立即重试下一节点,而不是直接返回给用户 - 收紧超时:
proxy_connect_timeout 3s、proxy_send_timeout 5s、proxy_read_timeout 8s,避免用户卡在失败连接上
四、验证要点:模拟真实故障链路
只测 “停主 Nginx” 不够,要覆盖完整路径:
- 手动
systemctl stop nginx在主节点,观察备用节点是否几秒内获得 VIP(ip addr show),并能立即响应请求 - 在切换过程中持续
curl -I http://VIP/login,确认 HTTP 状态码始终为 200,最多丢 1 次请求(VRRP 切换固有延迟) - 停掉一台后端服务,确认 access log 流量自动切到其他正常节点,且用户浏览器中 session Cookie 未失效、购物车/登录态仍保持
- 检查 Nginx error log,确认无大量
no live upstreams或反复重试失败记录











