Nginx 实现逐步放量
这个 Nginx 配置片段是一个基于 URL 和参数条件的路由规则,主要用于将请求代理到不同的后端服务。下面是逐行解释:
location ~* ^/diagrams/insert/edit {
-
location ~* ^/diagrams/insert/edit:定义一个 location 块,使用不区分大小写的正则表达式匹配(~*)以"/diagrams/insert/edit"开头的 URL 路径
if ($arg_user_id ~* "(\d+)$") {
set $user_id $arg_user_id;
}
-
if ($arg_user_id ~* "(\d+)$"):检查查询参数 user_id 是否以数字结尾(\d+表示一个或多个数字) -
set $user_id $arg_user_id:如果匹配,将 user_id 参数值赋给 $user_id 变量
if ($user_id ~* "([0-9][0-9])$") {
proxy_pass http://editor;
}
-
if ($user_id ~* "([0-9][0-9])$"):检查 $user_id 变量是否以两个连续数字结尾 -
proxy_pass http://editor:如果匹配,将请求代理到名为"editor"的后端服务
proxy_pass http://v3api;
-
默认情况下(即前面的 if 条件都不满足),将请求代理到名为"v3api"的后端服务
整体逻辑
这个配置的作用是:
-
匹配所有以"/diagrams/insert/edit"开头的请求(不区分大小写)
-
如果请求包含 user_id 参数且参数值是数字:
-
如果 user_id 以两个数字结尾(如12、34等),则将请求转发到 editor 服务
-
-
其他所有情况(包括没有 user_id 参数或 user_id 不符合条件),都将请求转发到 v3api 服务
这种配置常用于根据请求参数将流量路由到不同的后端服务,例如为特定用户群体提供不同的服务版本或功能。
如果你想实现 按 user_id 末尾两位数字放量 10% 的流量到 editor 服务(即只有约 10% 的请求会被代理到 editor,其余 90% 走默认的 v3api),可以使用 Nginx 的 split_clients 模块 或 map 指令 来实现概率分流。
方法 1:使用 split_clients 实现 10% 流量放量
split_clients 是 Nginx 提供的 A/B 测试、灰度发布功能,可以按比例分配流量。
# 在 http 块中定义流量分配规则
http {
# 定义一个变量 $traffic_split,基于 $user_id 进行 10% 分流
split_clients "${user_id}${remote_addr}" $traffic_split {
10% "editor"; # 10% 流量分配到 editor
* "v3api"; # 其余 90% 流量走 v3api
}
server {
location ~* ^/diagrams/insert/edit {
if ($arg_user_id ~* "(\d+)$") {
set $user_id $arg_user_id;
}
# 如果 user_id 以两位数字结尾,并且被分配到 editor 组
if ($user_id ~* "([0-9][0-9])$") {
set $service_group $traffic_split; # 使用 split_clients 结果
}
# 根据 $service_group 决定代理目标
if ($service_group = "editor") {
proxy_pass http://editor;
}
# 默认情况(包括未匹配或分配到 v3api 的情况)
proxy_pass http://v3api;
}
}
}
逻辑说明
-
split_clients基于$user_id+$remote_addr(防止同一用户多次请求被随机分配)计算哈希值,并按 10% editor / 90% v3api 分配。 -
仅当
$user_id以两位数字结尾时,才会进入流量分配逻辑。 -
最终根据
$service_group决定代理目标。
方法 2:使用 map + $request_id 实现随机 10% 放量
如果不想用 split_clients,也可以用 map 结合随机变量(如 $request_id)实现:
http {
# 定义一个 map,基于 $request_id(随机字符串)计算是否命中 10%
map $request_id $is_editor {
default 0;
# 取 $request_id 的某个字符(模拟随机)
~*^[0-9a-f]{1}0$ 1; # 大约 1/16 ≈ 6.25%(可调整)
~*^[0-9a-f]{2}0$ 1; # 可组合更多规则接近 10%
}
server {
location ~* ^/diagrams/insert/edit {
if ($arg_user_id ~* "(\d+)$") {
set $user_id $arg_user_id;
}
# 如果 user_id 以两位数字结尾,并且 $is_editor=1(命中 10%)
if ($user_id ~* "([0-9][0-9])$") {
set $is_eligible 1;
}
if ($is_eligible = 1) {
if ($is_editor = 1) {
proxy_pass http://editor;
}
}
proxy_pass http://v3api;
}

浙公网安备 33010602011771号