X-Accel-Limit-Rate 是由后端通过响应头传递给 Nginx 的动态限速指令(字节/秒),仅对 proxy_pass 等代理生效;需用 map 基于 $upstream_response_time 字符串匹配耗时区间映射限速值,并配合 add_header ... always 和 proxy_buffering off 在 location 中注入,确保响应头发送前生效。

在 Nginx 中,X-Accel-Limit-Rate 是一个由后端(如应用服务器)通过响应头传递给 Nginx 的指令,用于动态控制向客户端发送响应体时的速率(单位:字节/秒)。但注意:Nginx 本身不原生支持基于请求耗时(如 upstream_response_time)动态设置该头 —— 因为 X-Accel-Limit-Rate 是响应阶段生效的响应头,而耗时指标(如 $upstream_response_time)只能在日志或变量中使用,无法直接在响应头中参与条件计算。
不过,可通过 map + add_header(配合 proxy_pass 和 fastcgi_pass 等代理模块)实现“近似动态限速”:即在请求结束前,根据上游响应耗时预估并注入限速值。关键在于:限速逻辑必须在响应头发送前完成,且依赖于已知的耗时变量。以下是可行方案:
前提:启用响应头透传与变量支持
确保 Nginx 编译时启用了 --with-http_realip_module(非必需)和标准 proxy/fastcgi 模块;同时确认后端未覆盖或清除你将要注入的 X-Accel-Limit-Rate 头。
- 若用
proxy_pass,需开启proxy_buffering off或合理配置缓冲,避免响应体提前发送导致限速失效 -
X-Accel-Limit-Rate仅对proxy_pass/fastcgi_pass/scgi_pass/uwsgi_pass生效,对静态文件无效 - 该头值为整数(字节/秒),如
102400表示 100KB/s;设为0表示禁用限速
用 map 基于 upstream_response_time 映射限速值
map 指令可在请求处理早期(rewrite 阶段)将变量映射为新变量,但 $upstream_response_time 是在 upstream 完成后才填充的 —— 所以它不能直接用于 map 做实时判断。正确做法是:在 location 中用 add_header + always,结合内置变量(如 $upstream_response_time)进行简单运算(Nginx 1.13.2+ 支持基本算术):
map $upstream_response_time $limit_rate_val {
~^[0-9]+\.([0-9]{1,3})$ $1; # 提取小数点后三位(不推荐,精度低)
default 0;
}但上述方式不可靠。更实用的是:用 map 将耗时区间映射为预设限速档位:
map $upstream_response_time $dynamic_limit {
default 0;
~^0\. 512000; # < 1s → 500KB/s
~^1\. 256000; # 1.x s → 250KB/s
~^2\. 128000; # 2.x s → 125KB/s
~^[3-9]\. 64000; # 3–9.x s → 64KB/s
~^[1-9][0-9]\. 32000; # ≥10s → 32KB/s
}⚠️ 注意:$upstream_response_time 是字符串(如 "0.324"),正则匹配有效;但该变量仅在 upstream 结束后可用,因此 map 必须配合 add_header ... always 使用(否则 header 不会添加)。
在 location 中注入 X-Accel-Limit-Rate
在对应代理 location 中添加:
location /api/ {
proxy_pass http://backend;
proxy_buffering off; # 确保 add_header 在响应头阶段生效(重要!)
<pre class="brush:php;toolbar:false;"># 动态注入限速头(always 表示即使 error 也发送)
add_header X-Accel-Limit-Rate $dynamic_limit always;
# 可选:记录实际限速值用于调试
log_format with_limit '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream_time:$upstream_response_time limit:$dynamic_limit';
access_log /var/log/nginx/api.log with_limit;}
✅ 这样,当请求返回后,Nginx 会根据 $upstream_response_time 字符串匹配 map 规则,得到 $dynamic_limit,再通过 add_header ... always 注入响应头,最终触发 Nginx 内部限速逻辑。
注意事项与常见问题
-
add_header默认不继承,需在每个需要限速的location中显式写入 -
proxy_buffering off是关键:若开启缓冲,响应体可能已开始发送,此时添加限速头无效 -
$upstream_response_time在失败请求(如超时、502)中为空或为“-”,map会走 default 分支;建议搭配proxy_next_upstream和健康检查提升稳定性 - 若需更高精度(如按毫秒级线性限速),需改用 Lua(OpenResty)或外部服务做决策,Nginx 原生命令能力有限
- 该方案限速作用于 Nginx → Client 链路,不影响 upstream → Nginx 的传输速度
不复杂但容易忽略:限速值必须是整数,且仅对代理响应体生效;务必验证 add_header ... always 是否真实出现在响应头中(用 curl -I 测试),并确认后端未覆盖该头。

















