怎么配置 Nginx 实现灰度发布按权重分流流量

文章导读
在 Nginx 中实现基于权重的灰度发布,最直接的做法是在 upstream 模块中为不同后端服务器设置 weight 参数。这种方式适合无状态服务的简单按比例分流,但需注意会话保持与验证方法的配套配置。
📋 目录
  1. 核心配置步骤
  2. 配置生效与重载
  3. 验证分流是否生效
  4. 会话保持与权重冲突解决方案
  5. 灰度发布场景说明
  6. 常见坑与排查
  7. 参考来源
A A

在 Nginx 中实现基于权重的灰度发布,最直接的做法是在 upstream 模块中为不同后端服务器设置 weight 参数。这种方式适合无状态服务的简单按比例分流,但需注意会话保持与验证方法的配套配置。

先说结论:通过 upstream 权重配置可以实现基础的流量按比例分发,但默认不支持会话保持,且验证分流效果需后端配合或查看日志。

  • 适合:无状态服务、HTTP 短连接场景、新版本小流量随机测试
  • 先准备:确认后端服务健康状态、备份当前配置文件、规划好权重比例、配置后端返回标识或 Nginx 日志格式
  • 验收:通过批量请求统计后端标识分布、分析 Nginx 访问日志中的 $upstream_addr 字段

核心配置步骤

1. 编辑配置文件,通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/ 下的站点文件。

2. 定义 upstream 块,设置 weight 参数。权重越高,分配到的请求越多:

upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=1;
}

3. 在 server 块中引用 upstream:

server {
    listen 80;
    server_name your-domain.com;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

配置生效与重载

修改配置后必须先检查语法,再平滑重载,避免服务中断:

nginx -t && nginx -s reload

nginx -t 报错,请根据提示检查括号匹配或分号缺失。

怎么配置 Nginx 实现灰度发布按权重分流流量

验证分流是否生效

权重配置生效后,需通过以下两种方式进行验证,确保流量按预期分布。

方式一:后端服务返回标识

前提需要后端服务能在响应中返回自身标识(如 IP 或主机名)。以下以 Java Spring Boot 为例,在 Controller 中返回本地主机名:

@RestController
public class InfoController {
    @GetMapping("/info")
    public String getInfo() {
        return InetAddress.getLocalHost().getHostName();
    }
}

配置完成后,使用循环请求配合统计命令观察分布情况。例如发送 100 个请求:

for i in {1..100}; do curl -s http://your-domain.com/info; echo; done | sort | uniq -c

输出结果应大致符合权重比例(如 3:1)。

方式二:通过 Nginx 访问日志验证

若无法修改后端代码,可通过 Nginx 日志中的 $upstream_addr 字段验证。需在 http 块中配置自定义日志格式:

怎么配置 Nginx 实现灰度发布按权重分流流量
log_format upstream_log '$remote_addr - $upstream_addr - $request';
access_log /var/log/nginx/access.log upstream_log;

重载配置产生流量后,使用 awk 统计日志中不同后端 IP 的出现次数:

awk '{print $3}' /var/log/nginx/access.log | sort | uniq -c

字段位置取决于 log_format 定义,请根据实际情况调整 awk 列号。

会话保持与权重冲突解决方案

默认权重轮询不保证同一用户请求落到同一台服务器。涉及登录态的服务需配合会话保持方案,但需注意以下冲突:

  • ip_hash 限制:原生 Nginx 开启 ip_hash 后,weight 参数会失效,流量将强制按 IP 哈希分配,无法实现权重灰度。
  • 替代方案:若需同时支持权重分流和会话保持,建议使用第三方模块 nginx-upstream-sticky-module

配置示例(需编译支持 sticky 模块):

upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=1;
    sticky_cookie srv_id expires=1h domain=.your-domain.com path=/;
}

该方案通过 Cookie 实现粘性会话,同时保留权重分配能力。

灰度发布场景说明

权重分流属于“随机灰度”,流量分配不可控(无法指定特定用户)。若需基于用户特征(如 Header、Cookie、URI)进行精细灰度,需配合 map 指令或 if 判断:

map $http_x_canary $backend_version {
    default "backend_v1";
    "true" "backend_v2";
}

upstream backend_v1 { server 192.168.1.10:8080; }
upstream backend_v2 { server 192.168.1.11:8080; }

server {
    location / {
        proxy_pass http://$backend_version;
    }
}

常见坑与排查

  • 长连接影响:如果客户端保持长连接,请求分布可能不会严格符合权重比例,因为连接复用会导致请求集中在少数连接上。验证时建议使用短连接或清除 Keep-Alive。
  • 后端健康检查:修改权重后必须确保新后端服务已启动并健康,否则 Nginx 会将流量转发至故障节点导致 502 错误。建议配置 max_failsfail_timeout
  • 配置生效:修改后必须执行 reload,且确保新配置文件语法无误。
  • 日志权限:验证日志时确保当前用户有权限读取 /var/log/nginx/access.log

参考来源

  • Nginx 官方文档 - ngx_http_upstream_module - https://nginx.org/en/docs/http/ngx_http_upstream_module.html
  • Nginx Sticky Module - https://github.com/nginx-modules/nginx-upstream-sticky-module