Nginx 流量镜像配置文档-双轨国产化

Nginx 流量镜像配置文档(10% 比例采样)

适用文件:

  • http.conf

Nginx/OpenResty 版本:支持 split_clientsmirror 指令的版本(OpenResty ≥ 1.13.x / Nginx ≥ 1.13.x)。 部署形态:两份配置互为副本,结构相同,通常部署在不同节点或环境,共用同一套镜像策略。


一、概述

http.conf 中加入了一套**轻量级、可控比例的流量镜像(Traffic Mirroring / Shadowing)**机制:

  • 目标 :把生产线上经过 Nginx 的请求,按一定比例复制一份到镜像后端,用于影子流量分析、压测、问题复现等。

  • 核心原则

    1. 镜像请求不影响主链路业务(响应不返回给客户端)。

    2. 通过 split_clients 做 A/B 比例控制 ,本次设置为 10% 开启 / 90% 关闭

    3. 镜像后端通过 internal 内部 location 转发,对外不可直接访问

    4. 镜像链路设置严格的超时(连接 500ms、收发 3s),避免拖垮主链路。


二、详解

改动 1:在 server 块开头新增 split_clients

位置server 块内、location 之前,请求方法校验之后。

复制代码
if ( $request_method !~* GET|POST|OPTIONS ) {
    return 405;
}
​
# 流量镜像比例控制:10%
split_clients $request_id $mirror_ratio {
    10%     mirror_enable;
    *       mirror_disable;
}

作用

  • 使用 nginx 的 split_clients 指令,对每一个请求 (以 $request_id 作为 hash 输入)做稳定 hash 抽样:

    • 10% 的请求 $mirror_ratio = mirror_enable(允许镜像)。

    • 90% 的请求 $mirror_ratio = mirror_disable(禁止镜像)。

  • 由于 split_clients 基于 hash,同一请求 ID 的采样结果稳定,便于灰度分析。

2:在 internal_mirror_sn 中增加条件判断

复制代码
# 镜像流量内部 location
location = /internal_mirror_sn {
  internal;
  proxy_pass http://mirror_sn$request_uri;
​
  if ($mirror_ratio = mirror_disable) {
    return 404;
  }
​
  # 同步透传请求头
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Mirror-Flag "sn-traffic";
  ...
}

作用

  • 借助 nginx mirror 指令的"跳转到 internal location"机制,先到达 /internal_mirror_sn

  • 在真正发起后端转发前,二次校验 $mirror_ratio

    • 如果是 mirror_disable(即 90% 的请求),直接 return 404立刻丢弃镜像请求,不再占用上游连接;

    • 只有 mirror_enable 时才执行 proxy_pass 真正把请求打到镜像后端。

nginx mirror 指令本身不支持 做条件判断(它是无条件触发),所以必须借由 internal location + if 实现"按比例开关"。


三、整体流量走向与控制原理

1. 关键组件

组件 说明
split_clients $request_id $mirror_ratio 比例控制器,10/90 分流
mirror /internal_mirror_sn 镜像指令,在每个 location 中触发
location = /internal_mirror_sninternal 镜像接收与转发点
upstream mirror_sn 镜像后端集群(当前指向 国产化环境的SLB
proxy_next_upstream off 镜像失败不重试,避免阻塞主链路

2. 单请求完整流向图

复制代码
                 ┌─────────────────────────────────────────┐
  客户端请求 ──▶ │  Nginx ( 生产环境节点 server 块)            │
                 │                                         │
                 │  1) 方法校验 (GET/POST/OPTIONS 通过)     │
                 │  2) split_clients 按 $request_id 抽样    │
                 │     → 10% → mirror_enable                │
                 │     → 90% → mirror_disable              │
                 │  3) 匹配对应 location,正常 proxy_pass   │
                 │     到业务上游(主链路,不受影响)         │
                 │  4) 同时触发 mirror 指令                  │
                 └───────────────┬─────────────────────────┘
                                 │ (镜像)
                                 ▼
                 ┌─────────────────────────────────────────┐
                 │  location = /internal_mirror_sn          │
                 │  (internal,仅供内部跳转)               │
                 │                                         │
                 │  if ($mirror_ratio = mirror_disable)     │
                 │       return 404;  ← 丢弃(90% 请求)    │
                 │  else                                  │
                 │       proxy_pass http://mirror_sn$uri   │
                 │       → 10.248.135.95:20080             │
                 └─────────────────────────────────────────┘
                                 │
                                 ▼
                          镜像后端(用于影子分析)

3. 主链路 vs 镜像链路(关键区别)

维度 主链路 镜像链路
是否返回给客户端 ✅ 是 ❌ 否(响应丢弃)
失败是否影响业务 否(连接失败只记日志)
超时设置 通常 60s/180s 严格 500ms/3s
是否允许重试 通常 proxy_next_upstream on off(禁止重试)
是否带请求体 根据业务而定 mirror_request_body on(带 body)
采样比例 100% 10%

四、哪些流量走镜像,哪些不走?

1. 走镜像的 location(已显式声明 mirror /internal_mirror_sn

通过扫描两份配置,以下 location 均启用了镜像

业务模块 Location 前缀/精确路径 说明
工作流图 /workflow-diagram 工作流图代理
数字化监管 /szhjg//szhjg-rmp/ 数字化监管相关接口
PXF 代理 /pxf-proxy- HTTPS 上游代理
网关 /px-gateway 网关入口
登录 /login 登录接口
K8s API /k8s-api/ /k8s-api/api/xxx → /api/xxx
通用网关 /px-/sx-/fbs-/sn- 微服务网关调用
FDD /pxf-common-fdd 大文件上传
WebSocket /websocket/noticeWebsocket/chanelmoitorWebsocket/mpushWebsocket/nettyWebsocket WebSocket 入口
Nacos /nacos 注册中心 UI/API
AI/聊天 /chat/knowlwdge_base/ai- 智能问答相关

以上 location 内 10% 的请求会被镜像,90% 会在 internal 入口被丢弃。

2. 不走镜像的请求

  • 所有非 GET/POST/OPTIONS 方法(如 PUTDELETEPATCH):在 server 入口被 return 405 直接拒绝,不会进入任何 location,自然也不会被镜像。

  • 静态资源类 location (未配置 mirror):这些 location 直接返回本地文件,不发起镜像:

    • /error_page/

    • /

    • /.well-known/pki-validation/

    • /ht-portal/

    • /pxf-k8s-tool//res/

    • /pxf-(注意:这是静态资源分支,与 /px- 网关分支不同)

    • /common/

    • /index.html/pxf-(*)/index.html

  • 特殊 rewrite 重定向location = /pxf-sxservice-omarketservice/#/1rewrite ^ https://www.baidu.com/)--- 直接重定向,不进入 mirror 链路

3. 总结一句话

凡是配置了 mirror /internal_mirror_sn 的 location ,其请求中的 10% 会被同步复制一份发往镜像后端;未配置 mirror 的 location被 405 拦截的请求 永远不会走镜像。


五、延时分析

镜像链路设计了硬性短超时以保护主链路:

阶段 配置 超时值
建立连接 proxy_connect_timeout 500 ms
读取响应 proxy_read_timeout 3 s
发送请求 proxy_send_timeout 3 s
重试 proxy_next_upstream off 失败不重试
Keepalive keepalive 64keepalive_timeout 30skeepalive_requests 500 长连接复用

对主链路的影响

  • nginx mirror 指令默认行为是异步 ,镜像请求与主请求并行发送,主链路响应时间不会直接叠加镜像耗时

  • 唯一会影响主链路的场景 :镜像后端连接耗尽(极端情况),在 internal 中排队等待,但连接超时被限制在 500 ms 内。

  • 由于 mirror_request_body onPOST 等带 body 的请求会先把 body 落盘/缓存再镜像,body 较大时会有少量 I/O 开销。

实际经验值

场景 镜像对主链路延时的额外影响
镜像后端正常、空闲 < 1 ms(异步 + keepalive)
镜像后端慢 / 超时 主链路几乎无影响(500 ms 触发超时后丢弃)
大 body 镜像(>1 MB) 1~5 ms(body 缓存)
镜像后端宕机 主链路无影响(连接 500 ms 内失败并丢弃)

六、上游(upstream)配置说明

复制代码
upstream mirror_sn {
  server 国产化环境地址和端口;
  keepalive 64;
  keepalive_timeout 30s;
  keepalive_requests 500;
}
  • 如需高可用可扩展多台:

    复制代码
    upstream mirror_sn {
        server 1.1.1.1:80;
        server 1.1.1.2:80;
        keepalive 64;
        keepalive_timeout 30s;
        keepalive_requests 500;
    }
  • keepalive 64:每个 worker 与上游最多维持 64 条长连接,复用连接降低握手开销。

  • keepalive_requests 500:单条长连接最多处理 500 个请求后主动重建,避免长时间复用带来的资源泄漏。

  • keepalive_timeout 30s:空闲连接保持 30 秒。


七、镜像请求的关键 Header

/internal_mirror_sn 中透传了以下 header,便于后端识别与审计:

Header 用途
Host $host 保留原始域名
X-Real-IP $remote_addr 真实客户端 IP
X-Forwarded-For $proxy_add_x_forwarded_for 完整代理链路
X-Mirror-Flag sn-traffic 镜像流量标识,后端可据此区分影子流量与真实流量
Connection "" 关闭客户端侧的 Connection 头,配合 keepalive

镜像后端服务必须识别 X-Mirror-Flag: sn-traffic避免将影子流量写入生产库 / 发送通知 / 触发副作用


八、比例控制:如何调整采样率?

只需修改 split_clients 块即可(两文件同步修改):

复制代码
# 关闭镜像(全量丢弃)
split_clients $request_id $mirror_ratio {
    0%      mirror_enable;
    *       mirror_disable;
}
​
# 50% 镜像
split_clients $request_id $mirror_ratio {
    50%     mirror_enable;
    *       mirror_disable;
}
​
# 100% 全量镜像
split_clients $request_id $mirror_ratio {
    *       mirror_enable;
}

调整后 nginx -s reload 即可热生效(无需重启进程)。


九、部署与验证步骤

1. 语法检查

复制代码
nginx -t -c nginx.conf

2. 热加载

复制代码
nginx -s reload

3. 验证镜像是否生效

方法一:观察镜像后端 access log

  • 在 国产化服务上检查请求量是否符合 ~10% 比例。

  • 抽样日志中的 X-Mirror-Flag: sn-traffic header 是否存在。

方法二:观察 nginx 自带的 mirror log

复制代码
tail -f /var/logs/nginx/mirror_sn_access.log
tail -f /var/logs/nginx/mirror_sn_error.log

方法三:临时改为 100% 做冒烟测试

复制代码
split_clients $request_id $mirror_ratio {
    *       mirror_enable;   # 临时全量
}

验证通过后改回 10%。

4. 确认 90% 请求被正确丢弃

  • 抽样 mirror_sn_error.log,可见 404(被 if 丢弃的请求不会产生这条日志,nginx 会直接 short-circuit)。

  • 主链路响应时间不应出现明显异常波动。


十、故障排查清单

现象 可能原因 处理建议
镜像后端收到 0 请求 split_clients 写成 0%,或 internalif 误判 检查 $mirror_ratio 实际值,开启 debug log
主链路变慢 镜像后端连接耗尽 / body 太大 调小采样率、扩大 keepalive、限制 body 大小
镜像后端写入生产库 后端未识别 X-Mirror-Flag 后端增加拦截逻辑:识别到 X-Mirror-Flag 时跳过副作用
比例不准(差几个百分点) hash 抖动 + 业务低谷 正常现象,split_clients 是统计意义上的近似
reload 后配置未生效 nginx 不支持 split_clients 升级到 OpenResty ≥ 1.13.x 或 Nginx ≥ 1.13.x

十一、附录:完整配置文件(参考)

A. split_clients

复制代码
# 流量镜像比例控制:10%
split_clients $request_id $mirror_ratio {
    10%     mirror_enable;
    *       mirror_disable;
}

B. if 判断以及对应location下开启流量镜像

复制代码
if ($mirror_ratio = mirror_disable) {
    return 404;
}

        #在每个对应的location下开启
        mirror /internal_mirror_sn;
        mirror_request_body on;

C. 完整的镜像接收 location(参考现状)

复制代码
location = /internal_mirror_sn {
  internal;
  proxy_pass http://mirror_sn$request_uri;

  if ($mirror_ratio = mirror_disable) {
    return 404;
  }

  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Mirror-Flag "sn-traffic";

  proxy_http_version 1.1;
  proxy_set_header Connection "";

  proxy_connect_timeout 500ms;
  proxy_read_timeout 3s;
  proxy_send_timeout 3s;
  proxy_next_upstream off;

}

相关推荐
JNX_SEMI1 小时前
ATR2652 GNSS双频LNA:0.75dB噪声系数与22dB高增益设计
前端·单片机·嵌入式硬件·物联网·硬件工程
Macbethad2 小时前
基于TwinCAT的半导体刻蚀设备SCADA管理程序技术方案
运维·网络·数据库
拾年2752 小时前
Node.js 异步进化论:从 path 路径拼接到 fs 文件读取,我终于理解了回调地狱的救赎之路
前端·node.js
花颜yyds2 小时前
React Konva 开发基础速查手册
前端
小粉粉hhh2 小时前
Node.js(五)——编写接口
前端·javascript·node.js
Helen_cai2 小时前
OpenHarmony http 网络请求封装与全局拦截实战(API Version23 + 适配版)
网络·网络协议·http·华为·harmonyos
liulilittle2 小时前
Exhaustive drift-fix simulation V2 — KCC on shared-bottleneck wired path.
开发语言·网络·python·tcp/ip·计算机网络·信息与通信·通信
nuoxin1142 小时前
HR4988替代A4988-富利威
网络·人工智能·嵌入式硬件·fpga开发·dsp开发
MegatronKing2 小时前
AI时代我们要如何玩抓包测试
前端·后端·测试