Nginx 按照流量比例反向代理配置详解
在灰度发布、A/B 测试等场景中,我们常需要将流量按一定比例分发到不同后端服务。Nginx 提供了 split_clients 模块,配合 map 和 proxy_pass,可以轻松实现基于客户端特征的流量比例分配。本文将从 Nginx 安装、Systemd 管理、完整配置到临时调试方案,提供一份可直接复制使用的完整教程。
一、Nginx 安装(Ubuntu 22.04)
说明:以下操作以 root 用户执行。
# 1. 卸载系统自带 nginxapt remove nginx apt purge nginx nginx-common -y # 2. 更新系统并安装编译依赖sudoapt update sudoaptinstall -y libpcre3 libpcre3-dev zlib1g-dev openssl libssl-dev # 3. 下载并编译安装 Nginx(以 1.29.0 为例)wget http://nginx.org/download/nginx-1.29.0.tar.gz sudotar -zxvf nginx-1.29.0.tar.gz cd nginx-1.29.0/ ./configure --prefix=/usr/local/nginx/ make&&makeinstall默认安装路径为 /usr/local/nginx/,主程序为 /usr/local/nginx/sbin/nginx,配置文件为 /usr/local/nginx/conf/nginx.conf。
二、Nginx 的 systemd 管理文件
创建 systemd 服务文件 /etc/systemd/system/nginx.service:
[Unit] Description=The NGINX HTTP and reverse proxy server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/var/run/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/local/nginx/sbin/nginx -s stop PrivateTmp=true [Install] WantedBy=multi-user.target 启用并启动服务:
systemctl daemon-reexec systemctl enable nginx systemctl start nginx 三、完整的 Nginx 配置(按 50%:50% 比例分流)
配置文件路径:/usr/local/nginx/conf/nginx.conf
user root; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" "$upstream_addr"'; # 定义 upstream 与 split_clients(保持原逻辑) upstream backend_primary { server bigdata.doubbjt.com; } upstream backend_secondary { server bigdata-h101.doubbjt.com; } split_clients "${remote_addr}${http_user_agent}" $backend { 50% backend_primary; 50% backend_secondary; } # 新增:动态映射 Host 头 map $backend $target_host { backend_primary "bigdata.doubbjt.com"; backend_secondary "bigdata-h101.doubbjt.com"; default "bigdata.doubbjt.com"; # 兜底策略 } server { listen 80; server_name bigdata-ai.doubbjt.com; access_log /var/log/nginx/access.log main; location / { proxy_pass http://$backend; proxy_set_header Host $target_host; # 关键修改:动态 Host 头 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } } ✅ 核心要点:split_clients根据${remote_addr}${http_user_agent}哈希值决定流量走向;map将$backend映射为对应的Host值;proxy_set_header Host $target_host确保后端收到正确的 Host 头,避免 404/403。
四、临时调试:关闭流量分配,强制走主环境
在测试阶段,若需临时让所有流量走 backend_primary,可使用以下配置:
user root; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" "$upstream_addr"'; # 定义 upstream 与 split_clients(保持原逻辑) upstream backend_primary { server bigdata.doubbjt.com; } upstream backend_secondary { server bigdata-h101.doubbjt.com; } ### split_clients "${remote_addr}${http_user_agent}" $backend { ### 50% backend_primary; ### 50% backend_secondary; ### } # 新增:动态映射 Host 头 map $backend $target_host { backend_primary "bigdata.doubbjt.com"; backend_secondary "bigdata-h101.doubbjt.com"; default "bigdata.doubbjt.com"; # 兜底策略 } server { listen 80; server_name bigdata-ai.doubbjt.com; access_log /var/log/nginx/access.log main; # 临时新增:强制所有流量指向 backend_primary set $backend "backend_primary"; location / { proxy_pass http://$backend; proxy_set_header Host $target_host; # 关键修改:动态 Host 头 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } } 📌 调试完成后,删除set $backend "backend_primary";并取消注释split_clients块即可恢复分流。
五、验证方法
查看日志确认后端:
tail -f /var/log/nginx/access.log 日志末尾的 $upstream_addr 字段将显示实际代理到的后端地址。
访问测试:
curl -H "Host: bigdata-ai.doubbjt.com" http://<nginx服务器IP>/ 六、总结
本文提供了 从安装到上线的完整 Nginx 流量比例反向代理方案,所有配置均为可运行的完整版本,无任何省略。通过 split_clients + map + proxy_pass 的组合,可安全、高效地实现灰度流量控制。
⚠️ 注意事项:Nginx 必须编译时包含 http_split_clients_module(默认已包含);流量比例是统计意义上的均匀分布,非逐请求轮询;如需用户粘性(同一用户始终访问同一后端),建议结合 Cookie 或应用层方案。