如何在 Nginx 配置文件中实现基于 Cookie 的会话保持

文章导读
Nginx 开源版本身不支持原生的 Cookie 会话保持指令,该功能属于 Nginx Plus 商业特性或在开源版中需编译第三方模块;对于大多数开源版用户,建议优先评估 ip_hash 或应用层会话共享方案。
📋 目录
  1. 命令速用版
  2. 开源版编译第三方模块实操
  3. 如何验证模块是否生效
  4. 常见坑
  5. 参考来源
A A

Nginx 开源版本身不支持原生的 Cookie 会话保持指令,该功能属于 Nginx Plus 商业特性或在开源版中需编译第三方模块;对于大多数开源版用户,建议优先评估 ip_hash 或应用层会话共享方案。

先说结论:若必须基于 Cookie 保持会话且使用开源版,需引入第三方模块否则只能退而求其次使用 ip_hash;若使用 Nginx Plus 则可直接配置 sticky 指令。

  • 适合:后端服务无共享会话存储且需保持用户粘滞的场景
  • 先准备:确认 Nginx 版本是开源版还是 Plus 版,以及是否允许引入第三方模块
  • 验收:通过多次请求验证同一 Cookie 是否始终指向同一台后端服务器

命令速用版

# Nginx 开源版 (原生仅支持 ip_hash)\nupstream backend {\n    ip_hash;\n    server 192.168.1.10;\n    server 192.168.1.11;\n}\n\n# Nginx Plus (支持 sticky cookie)\nupstream backend {\n    sticky cookie srv_id expires=1h domain=.example.com path=/;\n    server 192.168.1.10;\n    server 192.168.1.11;\n}\n\n# 开源版 + 第三方模块 (推荐 nginx-sticky-module-ng,语法可能因版本而异)\nupstream backend {\n    sticky name=route_id expires=1h path=/;\n    server 192.168.1.10;\n    server 192.168.1.11;\n}

开源版编译第三方模块实操

若确定使用开源版且必须实现 Cookie 会话保持,需重新编译 Nginx 并注入第三方模块。以下是基于 commonly used fork nginx-sticky-module-ng 的实操步骤:

1. 获取源码
下载 Nginx 源码(版本需与当前运行版本一致或兼容)及第三方模块源码。

# 示例:获取第三方模块 (社区维护版本,地址可能变动)\ngit clone https://github.com/aizawa/nginx-sticky-module-ng.git\n\n# 下载对应版本的 Nginx 源码\nwget http://nginx.org/download/nginx-1.24.0.tar.gz\ntar -zxvf nginx-1.24.0.tar.gz\ncd nginx-1.24.0

2. 配置编译参数
使用 ./configure 命令,关键是指定 `--add-module` 路径。注意保留原有编译参数,可通过 nginx -V 查看。

如何在 Nginx 配置文件中实现基于 Cookie 的会话保持
# 查看原有编译参数\nnginx -V\n\n# 添加第三方模块重新配置 (示例)\n./configure \\\n    `--prefix`=/etc/nginx \\\n    `--sbin-path`=/usr/sbin/nginx \\\n    `--add-module`=/path/to/nginx-sticky-module-ng

3. 编译与替换
编译生成二进制文件并替换原有 Nginx 程序,随后重载配置。

make\nsudo cp objs/nginx /usr/sbin/nginx/\nsudo nginx -t\nsudo nginx -s reload

如何验证模块是否生效

1. 检查编译模块列表
在执行编译前,可使用 nginx -V 查看当前是否已包含 sticky 相关模块。若输出中无相关模块信息,则原生不支持 sticky 指令。

nginx -V 2>&1 | grep -i sticky

2. 检查响应头
使用 curl -v http://your-domain.com 发起请求,观察响应头中是否包含 Set-Cookie 字段,且字段名与配置一致(如 srv_idroute_id)。

如何在 Nginx 配置文件中实现基于 Cookie 的会话保持

3. 携带 Cookie 多次请求
使用 curl -b "route_id=xxx" http://your-domain.com 多次发起请求,同时查看后端服务器的访问日志。若配置生效,所有携带相同 Cookie 的请求日志应出现在同一台后端服务器的日志文件中。

4. 后端日志确认
在后端应用中打印服务器主机名或 IP。连续刷新页面,若会话保持生效,页面显示的服务器标识不应发生变化。

常见坑

1. 开源版误用指令
很多教程直接给出 sticky 配置但未说明需第三方模块,导致开源版用户配置重载失败。务必先 nginx -t,若报错 unknown directive "sticky" 即表示未编译该模块。

2. 第三方模块语法差异
不同 fork 版本的第三方 sticky 模块指令参数可能不同(如 name= 还是 cookie=),编译前请查阅对应模块的 README 说明,不要直接复制配置。

如何在 Nginx 配置文件中实现基于 Cookie 的会话保持

3. ip_hash 的局限性
若使用开源版原生的 ip_hash,当客户端网络切换导致 IP 变化时,会话会中断。且 NAT 环境下多个用户可能共享同一出口 IP,导致负载不均。

4. 升级断裂风险
第三方模块非官方维护,升级 Nginx 版本时可能需重新编译,存在兼容性风险。生产环境引入前需在测试环境充分验证,并锁定 Nginx 版本避免意外升级。

5. Cookie 属性配置
若站点启用 HTTPS,建议在 Cookie 配置中开启 secure 属性,防止 Cookie 通过明文传输。同时注意 domainpath 的设置,避免浏览器拒绝写入。

参考来源

  • Nginx 官方文档 - ngx_http_upstream_module (ip_hash 指令说明)
  • Nginx Plus 管理员指南 - NGINX Load Balancer (sticky 指令说明)
  • GitHub - nginx-sticky-module-ng (第三方模块源码参考)