一、引言:为什么需要 sticky 模块?

在使用 Nginx 作为反向代理进行负载均衡时,一个经典难题是 会话保持(Session Persistence)。用户的请求可能会被分发到不同的后端应用服务器(如 Tomcat, Node.js),而这些服务器之间通常不共享 Session 数据,导致用户频繁“掉线”。

Nginx 自带的 ip_hash 策略虽然能解决部分问题,但它存在致命缺陷:

  • 受代理/CDN 影响:Nginx 看到的是代理服务器的 IP,而非真实用户 IP,导致大量用户被错误地路由到同一台服务器,造成严重负载不均。
  • 无法应对动态扩缩容

为了解决这个问题,社区开发了 nginx-sticky-module 这个强大的第三方模块。它通过 植入 Cookie 的方式,精准地将同一用户的请求始终路由到同一台后端服务器,完美实现了会话保持。

💡 核心价值
sticky 模块提供了一种比 ip_hash 更精准、更可靠的会话保持机制,是开源 Nginx 实现粘性会话的最佳实践!

二、准备工作:环境与依赖

由于 sticky 是一个第三方模块,我们需要从源码重新编译 Nginx 来集成它。

1. 系统环境

本文以 CentOS 7 / Rocky Linux 8 为例。

2. 安装编译依赖

sudo yum install -y gcc gcc-c++ make libtool pcre pcre-devel openssl openssl-devel zlib zlib-devel

3. 下载 Nginx 源码

请务必下载与你当前生产环境相同版本的 Nginx 源码,以避免兼容性问题。

# 例如,下载 Nginx 1.24.0
cd /usr/local/src
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz

4. 下载 sticky 模块源码

nginx-sticky-module 有多个分支,推荐使用维护较好的 nginx-sticky-module-ng

cd /usr/local/src
wget https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/08a395c66e42.zip
unzip 08a395c66e42.zip
# 解压后会得到一个类似 "nginx-goodies-nginx-sticky-module-ng-08a395c66e42" 的目录
mv nginx-goodies-nginx-sticky-module-ng-08a395c66e42 nginx-sticky-module-ng

三、核心步骤:编译并集成 sticky 模块

1. 查看现有 Nginx 的编译参数(重要!)

为了保证新编译的 Nginx 功能完全一致,我们需要先获取当前 Nginx 的编译参数。

nginx -V

你会看到类似如下的输出:

configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx ... --with-http_ssl_module ...

复制 configure arguments 后面的所有内容。

2. 进入 Nginx 源码目录并配置

cd nginx-1.24.0
# 在原有参数的基础上,加上 --add-module 指向 sticky 模块的路径
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
... # 这里是你之前复制的所有原有参数
--add-module=/usr/local/src/nginx-sticky-module-ng

3. 编译(但不要安装!)

执行 make 命令进行编译。这一步不会覆盖你现有的 Nginx 安装,只会生成一个新的可执行文件。

make

编译成功后,新的 Nginx 可执行文件位于 objs/nginx

4. 备份并替换原 Nginx 二进制文件

# 备份原文件
sudo cp /usr/sbin/nginx /usr/sbin/nginx.bak
# 替换为新编译的文件
sudo cp objs/nginx /usr/sbin/nginx

5. 验证模块是否加载成功

nginx -V 2>&1 | grep -o with-http_sticky_module

如果输出 with-http_sticky_module,则说明模块已成功集成。

四、配置与实战:启用 sticky 负载均衡

现在,我们可以在 Nginx 配置文件中使用 sticky 指令了。

1. 基本配置示例

编辑你的 nginx.conf 文件,在 upstream 块中添加 sticky 指令。

upstream backend {
    # 启用 sticky 模块
    # name: Cookie 名称
    # expires: Cookie 过期时间
    # path: Cookie 作用路径
    sticky cookie srv_id expires=1h domain=.yourdomain.com path=/;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}
server {
    listen 80;
    server_name yourdomain.com;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

2. 关键参数详解

  • name: 客户端 Cookie 的名称。默认为 route
  • expires: Cookie 的过期时间。可以是 1h (1小时), 30m (30分钟), 或 max (永不过期)。
  • domain: Cookie 的作用域。设置为你的主域名(如 .yourdomain.com)可以让子域名也共享此 Cookie。
  • path: Cookie 的作用路径。通常设为 /
  • hash=md5|sha1: 用于生成后端服务器标识的哈希算法。默认是 md5

3. 工作原理

  1. 首次访问:客户端请求头中没有 srv_id Cookie。Nginx 根据负载均衡策略(如轮询)选择一台后端服务器,并在响应头中植入 Set-Cookie: srv_id=xxx; ...
  2. 后续访问:客户端在请求头中携带 Cookie: srv_id=xxx。Nginx 解析此 Cookie,直接将请求转发给上次分配的那台服务器。

五、验证与排错

1. 验证会话保持

  • 使用浏览器开发者工具,观察首次响应是否包含 Set-Cookie
  • 刷新页面,检查后续请求的 Cookie 头是否包含 srv_id
  • 在后端应用服务器上打印请求日志,确认同一用户的请求始终落在同一台服务器上。

2. 常见问题与解决

  • 问题1:编译报错
    • 原因sticky 模块版本与 Nginx 版本不兼容。
    • 解决:尝试寻找与你 Nginx 版本匹配的 sticky 模块分支,或修改模块源码中的兼容性代码(通常涉及 ngx_http_upstream_srv_conf_t 结构体)。
  • 问题2:Cookie 未生效
    • 原因:客户端禁用了 Cookie,或者 domain/path 配置不正确。
    • 解决:检查浏览器设置,并确保 domain 配置与你的访问域名匹配。
  • 问题3:后端服务器宕机
    • 注意sticky 模块本身不包含健康检查功能。你需要配合 max_fails 和 fail_timeout 参数,或使用外部健康检查脚本,才能自动剔除故障节点。

六、结语

到此这篇关于Nginx使用sticky模块完成对Nginx的负载均衡(最佳实践)的文章就介绍到这了,更多相关Nginx sticky负载均衡内容请搜索教程之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持教程之家!

觉得上面的内容有用吗?快来点个赞吧!

点赞() 我要打赏

温馨提示 : 本站内容来自会员投稿以及互联网,所有源码及教程均为作者总结编辑,请大家在使用过程中提前做好备份,以免发生无法预知的错误,源码类教程请勿直接用于生产环境!

 可能感兴趣的文章