API网关入门:Nginx实现灰度发布与流量切分

API网关入门:Nginx实现灰度发布与流量切分

你要上线一个新功能。重构了代码,改了数据库结构,测试环境跑了一周,没问题。但你还是不敢直接全量上线。万一挂了,用户全炸。

如果能让1%的用户先试,没问题再逐步扩大到100%,就好了。

这就是灰度发布。Nginx能帮你实现。不需要改代码,加几行配置就行。


先看一个数据

某大型网站统计,引入灰度发布机制后,线上故障导致的大范围服务中断减少了70%。灰度发布让“坏版本”只影响一小部分用户,发现问题可以秒级回滚,不影响绝大多数人。

你不灰度,就是在赌。赌你的代码没bug,赌你的测试覆盖了所有场景,赌用户不会用你没想到的方式操作。


灰度发布的三种常见策略

策略适用场景实现方式
按用户ID分流用户维度灰度,体验一致split_clients对user_id取模
按IP分流内部测试、地域灰度geomap匹配IP段
按Cookie/Header分流指定测试用户map读取Cookie值

核心思路:把流量分成两份,一份去新版本,一份去老版本。Nginx作为反向代理,根据某个标识(用户ID、IP、Cookie)决定请求发到哪个后端。


配置一:按用户ID分流

最常用的方式。把用户ID哈希后取模,比如前10%的用户走新版本。

nginx

# 定义两个后端
upstream backend_old {
    server 192.168.1.10:8080;
}

upstream backend_new {
    server 192.168.1.11:8080;
}

# 根据user_id参数分流
split_clients "${arg_user_id}" $backend {
    10%     backend_new;
    *       backend_old;
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://$backend;
        proxy_set_header Host $host;
    }
}

split_clients使用MurmurHash2对${arg_user_id}(URL参数中的user_id)做哈希,按百分比分配。同一个user_id永远分配同一个后端,用户体验一致。

触发灰度:http://api.example.com/getUser?id=12345,id的后几位决定走新老版本。用户无感知,不需要前端配合。


配置二:按Cookie分流(指定用户)

给特定用户打标签,让他们走新版本。比如内部员工、种子用户。

nginx

# 读取Cookie中的gray_flag
map $cookie_gray $backend {
    default   backend_old;
    "on"      backend_new;
}

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

实现步骤:给测试用户的浏览器设置一个Cookiegray=on,他们的请求自动走新版本。其他人不受影响。Cookie设置可以在登录时根据用户等级下发,或手动通过浏览器开发者工具添加。

javascript

// 前端设置Cookie
document.cookie = "gray=on; path=/; max-age=86400";

配置三:按IP分流

nginx

# 定义IP段
geo $gray_ip {
    default 0;
    192.168.1.0/24 1;   # 公司内网走新版
    10.0.0.0/8 1;       # 办公网
}

map $gray_ip $backend {
    0   backend_old;
    1   backend_new;
}

内网IP走新版本,用于内部测试。外部用户还是老版本,测试通过后再逐步开放。


配置四:百分比流量逐步递增

灰度发布是一个过程:1% → 10% → 50% → 100%。每次改配置,重载Nginx。

nginx

split_clients "${arg_user_id}" $backend {
    1%     backend_new;   # 第一阶段:1%
    *      backend_old;
}

上线后没问题,改配置:

nginx

split_clients "${arg_user_id}" $backend {
    10%     backend_new;
    *       backend_old;
}

nginx -s reload热重载,连接不中断。

逐步放量到100%后,把proxy_pass直接指向新版本,下线旧后端配置。

回滚:发现问题,把百分比改回0%,重载,秒级回滚。


进阶:结合多种条件

复杂场景下,可组合使用:优先按Cookie,没有Cookie再按user_id。

nginx

map $cookie_gray $backend {
    "on"    backend_new;
    default backend_old;
}

split_clients "${arg_user_id}" $backend_fallback {
    5%      backend_new;
    *       backend_old;
}

# 如果Cookie没设,用fallback
set $backend_target $backend;
if ($backend_target = "backend_old") {
    set $backend_target $backend_fallback;
}

proxy_pass http://$backend_target;

逻辑:有Cookiegray=on走新版,否则按5%比例分流。


注意事项

1. 区分状态(session)问题
用户灰度期间产生了新数据(数据库、Redis),一旦回滚到旧版本,新版格式的数据旧版可能读不懂。建议灰度只影响读请求,写请求统一走老版本,或确保新旧版本数据完全兼容。

2. 数据库兼容
新旧版本同时存在,数据库schema必须兼容两者。不能在新版里加一个旧版不认识的字段就发布。

3. 缓存隔离
不同版本的缓存key要区分,避免新版写了缓存,老版读到错误格式的数据。

4. 监控
灰度期间要分别监控新旧版本的错误率、响应时间。Nginx可以配置不同upstream的日志分开记录,或用$upstream_addr变量标记。


真实案例

一个SaaS公司,重构了核心API。用Nginxsplit_clients指令,先切5%流量到新服务。观察了两天,错误率无变化,响应时间还快了10%。逐步提升到20%、50%、100%。全程无用户感知。

他们说:“没有灰度,我们绝对不敢这么重构。”


最后一句

灰度发布不是大公司的专利。Nginx几行配置就能实现。不用改代码,不用引入新组件。

下次上线重要功能,别直接全量。先给1%用户试试。有问题,改个配置就回滚了。没问题,逐步放大到100%。

你的用户不需要知道你在灰度。他们只需要服务稳定。灰度让你既稳定又快速。

知识库

服务器缓存策略:Redis命中率从30%到90%

2026-6-3 18:10:29

知识库

服务器文件权限详解:777为什么是灾难?

2026-6-4 18:00:33

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧