网站灰度发布平滑更新版本:零基础Nginx分流实操教程
什么是灰度发布?为什么需要平滑更新版本?
灰度发布(又称金丝雀发布)就是让新版代码只对一小部分用户生效,其余用户继续使用旧版。
等你确认新版本稳定后,再逐步扩大范围,最终全部切换。
这样做的好处是:
- 风险可控:即使新版本有bug,也只影响少量用户。
- 快速回滚:发现异常立刻切回旧版,几秒钟完成。
- 平滑体验:用户不会突然发现整个网站变了样。
本文以最常用的 Nginx + Cookies/Cookie分流 为例,帮你从零搭建一套完整的灰度发布流程。
---
第一步:做好准备工作
- 一台装有Nginx的服务器(CentOS 7/Ubuntu 20.04 都行)。未安装的参考官方文档或者直接用宝塔面板一键部署。
- 新旧两个版本的网站代码。假设旧版放在
/var/www/old,新版放在/var/www/new。 - 一个二级域名(例如 grey.example.com) 或者直接用主域名,这里用主域名演示。
- 确认Nginx已开启HTTP模块(默认都带)。
如果你用的是宝塔面板,请在“网站”菜单里先添加好站点,把新旧代码分别上传到不同目录。
---
第二步:配置Nginx按Cookie分流
核心思路:给一小部分用户的浏览器种一个特殊的Cookie(例如 version=new),Nginx根据这个Cookie决定转发到新版本还是旧版本。
这样用户不会因为IP变动而切来切去。
2.1 修改Nginx配置文件
假设你的站点配置文件在 /etc/nginx/conf.d/example.com.conf(宝塔则是在 /www/server/panel/vhost/nginx/example.com.conf),
打开后,
在 server 块内添加如下代码:
# 定义一个map,根据Cookie值决定使用哪个版本
map $cookie_version $version_root {
default /var/www/old; # 默认走旧版
new /var/www/new; # 如果Cookie version=new 则走新版
}
server {
listen 80;
server_name example.com;
root $version_root; # 动态根目录
index index.html index.php;
# 静态资源配置(略)
# ...
}
说明:$cookie_version是Nginx内置变量,读取名为version的Cookie值。如果值为new,根目录切换到新版代码。
2.2 如何给指定用户设置这个Cookie?
方法有很多,最简单的是在页面或入口加一段JavaScript:
// 设置Cookie,有效期7天
function joinGrayVersion() {
document.cookie = "version=new; path=/; max-age=" + (7*24*60*60);
location.reload();
}
you也可以通过在Nginx里用 add_header Set-Cookie 来针对部分IP自动设置(更专业)。
比如想让公司内部测试IP自动加入灰度:
if ($remote_addr ~* "192\.168\.1\.(100|101)") {
add_header Set-Cookie "version=new; path=/; max-age=86400";
}
2.3 测试配置
保存文件后,执行:
nginx -t
如果提示 syntax is ok,就重新加载Nginx:
systemctl reload nginx
# 或者 service nginx reload
---
第三步:逐步释放流量(灰度比例调整)
上面的Cookie方法是主动选择,适合内测。
如果你想随机分配一定比例的用户到新版,可以用 split_clients 模块。
3.1 使用 split_clients 随机分流
http {
# 定义分流规则:以客户端IP+User-Agent混合哈希,决定是否走新版
split_clients "${remote_addr}${http_user_agent}" $version_flag {
10% "new";
* "old";
}
map $version_flag $version_root {
default /var/www/old;
new /var/www/new;
}
}
10%表示10%的流量会分配到new组。- 你可以慢慢把这个比例增加到 20%、50%,直到100%。
- 修改比例后记得
nginx -t && systemctl reload nginx。
3.2 结合Cookie做更精细的控制
如果你想同时支持“固定用户测试”和“随机流量”,可以用多层判断:优先级Cookie > 随机。
上述map已经实现了,因为 $cookie_version 在 map 里会被优先匹配(Nginx map的匹配顺序是精确匹配优先于通配)。
---
第四步:避坑指南(非常重要)
- 新旧代码不能共用同一个Session或数据库写入路径。
如果旧版写入 tmp/session,新版也写同一个路径,会导致 session 冲突。
建议新旧版本使用不同的Session存储目录,或者使用Redis并配置不同前缀。
- 静态资源缓存。
如果新版改了CSS/JS,用户浏览器可能还在用缓存。
建议在Nginx里配置 add_header Cache-Control no-cache; 或者给静态文件加版本号(例如 ?)。
v=202503
- 数据库结构变更。
如果新版新增了数据库字段,旧版插入数据时会报错。
你需要先用迁移脚本兼容旧版,或者让灰度用户使用独立的数据库副本。
- Nginx reload不会中断已建立的连接,但
split_clients是实时生效的,下次请求就重新分配。所以用户可能每次刷新都切换版本?
解决办法:配合 map 和 $cookie_version 固定用户的分组,或者使用 sticky 模块。
简单起见,先用Cookie绑定一次,后面就不变了。
---
第五步:效果验证与故障回滚
5.1 验证灰度是否生效
- 检查日志:Nginx访问日志(默认
/var/log/nginx/access.log)会显示请求的root路径,你可以按时间筛选,查看哪些请求走了新版目录。 - 用浏览器测试:清除Cookie后访问,应看到旧版;然后执行上面的JavaScript设置Cookie,刷新后看到新版。
- 查看响应头:可以在Nginx配置中添加
add_header X-Gray-Version $version_root;,然后通过浏览器开发者工具查看请求响应头,确认走的是哪个版本。
5.2 发现异常怎么办?
立刻回滚!
- 如果是
split_clients方式:将比例改回0%,然后 reload。 - 如果是Cookie方式:在Nginx里删除
add_header Set-Cookie相关语句,reload即可。 - 或者直接修改
root指向旧版目录,reload。
回滚后检查用户反馈,等修复后再重新开启灰度。
---
总结
灰度发布是网站迭代的必备技能。
本文用Nginx的 map + split_clients 实现了一套轻量级方案,零基础也能在半小时内跑通。
关键点就三个:
- 分流规则:用Cookie或随机哈希。
- 版本目录隔离:新旧代码不共用数据。
- 快速回退机制:改比例、删配置都行。
你可以在测试服务器上先练一遍,再正式上线。
如果遇到报错,优先检查Nginx配置语法(nginx -t)和日志中的具体错误。
祝你平滑升级成功!