Nginx 实现逐步放量

这个 Nginx 配置片段是一个基于 URL 和参数条件的路由规则,主要用于将请求代理到不同的后端服务。下面是逐行解释:

nginx
 
复制
 
下载
location ~* ^/diagrams/insert/edit {
  • location ~* ^/diagrams/insert/edit:定义一个 location 块,使用不区分大小写的正则表达式匹配(~*)以"/diagrams/insert/edit"开头的 URL 路径

nginx
 
复制
 
下载
            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 变量

nginx
 
复制
 
下载
            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"的后端服务

nginx
 
复制
 
下载
            proxy_pass http://v3api;
  • 默认情况下(即前面的 if 条件都不满足),将请求代理到名为"v3api"的后端服务

整体逻辑

这个配置的作用是:

  1. 匹配所有以"/diagrams/insert/edit"开头的请求(不区分大小写)

  2. 如果请求包含 user_id 参数且参数值是数字:

    • 如果 user_id 以两个数字结尾(如12、34等),则将请求转发到 editor 服务

  3. 其他所有情况(包括没有 user_id 参数或 user_id 不符合条件),都将请求转发到 v3api 服务

这种配置常用于根据请求参数将流量路由到不同的后端服务,例如为特定用户群体提供不同的服务版本或功能。

 
if ($user_id ~* "([0-9][0-9])$") { proxy_pass http://editor; } 放量百分之10
 
 
修改
 

如果你想实现 按 user_id 末尾两位数字放量 10% 的流量到 editor 服务(即只有约 10% 的请求会被代理到 editor,其余 90% 走默认的 v3api),可以使用 Nginx 的 split_clients 模块 或 map 指令 来实现概率分流。


方法 1:使用 split_clients 实现 10% 流量放量

split_clients 是 Nginx 提供的 A/B 测试、灰度发布功能,可以按比例分配流量。

nginx
 
复制
 
下载
# 在 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;
        }
    }
}

逻辑说明

  1. split_clients 基于 $user_id + $remote_addr(防止同一用户多次请求被随机分配)计算哈希值,并按 10% editor / 90% v3api 分配。

  2. 仅当 $user_id 以两位数字结尾时,才会进入流量分配逻辑。

  3. 最终根据 $service_group 决定代理目标。


方法 2:使用 map + $request_id 实现随机 10% 放量

如果不想用 split_clients,也可以用 map 结合随机变量(如 $request_id)实现:

nginx
 
复制
 
下载
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;
        }
posted @ 2025-04-21 16:35  GaoYanbing  阅读(61)  评论(0)    收藏  举报