Nginx 实现会话保持(Session Persistence)
Nginx 实现会话保持Session Persistence主要有3 种方式生产环境最常用的是sticky cookie和ip_hash而sticky learn是更灵活的高级方案。一、三种方式对比先看结论方式原理优点缺点生产推荐度ip_hash按客户端 IP 哈希分配简单无需配置代理 IP 会失真后端宕机会丢会话⭐⭐ 简单场景sticky cookieNginx 插入 cookie客户端携带精准不受 IP 影响需要浏览器支持 cookie⭐⭐⭐⭐⭐首选sticky learn动态学习请求与后端映射兼容性好不修改响应内存消耗仅 Nginx Plus 或第三方模块⭐⭐⭐⭐ 大并发场景二、方式一ip_hash最简单配置示例upstream tomcat_cluster { ip_hash; # 开启 IP 哈希会话保持 server 192.168.1.10:8080; server 192.168.1.11:8080; }工作原理Nginx 对客户端 IP 地址计算哈希值同一 IP 的请求始终落在同一台后端服务器上适用场景客户端 IP 相对固定如企业内网对会话保持要求不苛刻的场景典型问题用户通过公司统一出口上网 → 所有用户看起来像一个 IP → 全部落到同一台服务器上后端服务器宕机 → 该服务器上的会话全部丢失三、方式二sticky cookie生产首选需要编译第三方模块Nginx 官方开源版原生不支持需要编译nginx-sticky-module-ng模块Nginx Plus 商业版原生支持配置示例upstream tomcat_cluster { sticky cookie srv_id expires1h domain.example.com path/; server 192.168.1.10:8080; server 192.168.1.11:8080; }参数说明参数说明cookie srv_id设置 cookie 名称可自定义expires1hcookie 有效期 1 小时domain.example.comcookie 生效的域名path/cookie 生效的路径工作原理关键Tomcat2Tomcat1Nginx用户Tomcat2Tomcat1Nginx用户1. 首次请求无 cookie2. 选择一台后端如 tomcat13. 响应内容4. 响应 Set-Cookie: srv_idtomcat15. 后续请求携带 cookie6. 根据 cookie 直接发往 tomcat1优势精准不受代理 IP 影响透明后端 Tomcat 无需任何改造兼容性好支持stickyfallback做高可用四、方式三sticky learnNginx Plus 或 OpenResty配置示例Nginx Plusupstream tomcat_cluster { zone upstream_zone 64k; sticky learn create$upstream_cookie_sessionid lookup$cookie_sessionid zoneclient_sessions:1m; server 192.168.1.10:8080; server 192.168.1.11:8080; }与传统 sticky cookie 的区别对比维度sticky cookiesticky learn谁插入 cookieNginx 插入新 cookie不插入 cookie学习应用已有的 cookie后端应用要求无要求应用需要自己生成一个sessionidcookie升级兼容性已有 cookie 可能变化无感知应用自己的 cookie 不变典型使用场景新项目无历史包袱老项目改造、不想改现有 cookie 逻辑五、三种方式选型决策树是否可容忍不可容忍是否需要会话保持客户端 IP 是否相对固定会话丢失容忍度使用 sticky cookieip_hash不想改造后端应用sticky cookie 或 ip_hashsticky learn学习应用已有 cookie六、生产环境最佳实践推荐方案sticky cookie 共享存储兜底upstream tomcat_cluster { sticky cookie srv_id expires1h; server 192.168.1.10:8080 max_fails3 fail_timeout30s; server 192.168.1.11:8080 max_fails3 fail_timeout30s; }为什么还要做共享存储即使 Nginx 做了会话保持如果后端 Tomcat 宕机用户会话还是会丢失。所以真正的生产高可用Nginx 会话保持 Redis 共享存储Nginx 保证同一用户的请求尽量发到同一台服务器性能好、减少跨节点读取 sessionRedis 保证即使那台服务器宕机其他服务器也能从 Redis 中读取 session七、排查建议如果配置了会话保持但还是不生效现象可能原因排查方法请求总是落到不同服务器cookie 未携带打开浏览器开发者工具 → Application → Cookies检查 cookie 是否存在ip_hash 不生效多级代理X-Forwarded-For使用real_ip_header获取真实 IP负载严重不均ip_hash 算法分布不均考虑改用 sticky cookie八、一句话总结Nginx 实现会话保持最常用的方式是通过sticky cookie给客户端打标记让后续请求始终落到同一台后端服务器上。但别忘了Nginx 会话保持 Redis 共享存储 真正的生产高可用。