nginx 不存在 $upstream_bytes_sent 变量,该变量为虚构;应使用 $request_length 准确反映发往上游的请求总字节数(含请求行、头及体),结合路径隔离与 tls 上下文实现安全链路吞吐监控。

$upstream_bytes_sent 不是 Nginx 的有效内置变量,Nginx 官方文档及所有可靠实践资料中均未定义该变量。你无法通过 log_format 捕获 $upstream_bytes_sent —— 它不存在,配置后将始终为空字符串或导致日志字段缺失,无法用于监控。
你需要的是反映 Nginx 向上游(安全后端)实际发送的数据量,即“请求体字节数”。Nginx 提供的对应变量是:
- ✅
$request_length:完整客户端请求长度(字节),包含请求行、头、请求体(如 POST body)。这是最贴近“发给上游数据量”的可靠指标,尤其在启用proxy_pass_request_body on(默认)时,它基本等于转发给 upstream 的总负载。 - ✅
$body_bytes_sent:Nginx 发给客户端的响应体字节数(注意:这是出向,非上游方向)。 - ❌
$upstream_bytes_sent:不存在,无对应实现,切勿在log_format中使用。
如何精准监控发往安全上游各路径的实际网络吞吐
关键不是虚构变量,而是用对已有变量,并结合路径区分与上下文标记:
1. 使用 $request_length 作为上游入向请求体积代理
它稳定、实时、无需额外模块,且在 proxy 场景下准确反映 Nginx 转发给 upstream 的原始请求大小(含 JSON、文件上传等 body):
log_format upstream_send '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'request_len=$request_length '
'upstream="$upstream_addr" '
'path="$request_uri" ';
? 示例:
POST /api/v2/encrypt上传 1.2MB 密文 →$request_length显示1256789,即真实发往上层加密服务的数据量。
2. 按路径/上游分组,隔离监控目标
避免日志混杂。为不同安全路径(如 /auth/, /sign/, /vault/)配置独立 access_log,便于按业务域统计吞吐:
location /auth/ {
proxy_pass https://auth-upstream;
access_log /var/log/nginx/auth_upstream.log upstream_send;
}
location /vault/ {
proxy_pass https://vault-upstream;
access_log /var/log/nginx/vault_upstream.log upstream_send;
}
这样可直接用 awk '{sum += $NF} END {print sum}' /var/log/nginx/vault_upstream.log 统计某路径累计发送字节数。
3. 补充关键上下文,识别异常流量
单看字节数不够,需关联安全性上下文:
- 加入
$ssl_protocol/$ssl_cipher:确认是否走 TLS 1.2+、是否使用强密钥套件 - 加入
$http_authorization截断(如substr($http_authorization, 0, 10))或$http_x_api_key:验证认证方式是否合规 - 加入
$upstream_response_time和$upstream_status:判断大请求是否引发超时或 5xx(例如:大文件上传触发后端限流)
log_format secure_upstream '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'len=$request_length '
'upstream=$upstream_addr '
'tls="$ssl_protocol/$ssl_cipher" '
'rt=$upstream_response_time '
'upst=$upstream_status ';
4. 注意边界情况,避免误判
- 若启用
proxy_buffering off或chunked_transfer_encoding on,$request_length仍准确(它是接收完 client request 后计算的总长) - 若使用
proxy_set_body或rewrite ... break;修改请求体,$request_length不变(它反映原始请求),此时需配合map+ 自定义变量标记重写行为 - 静态资源(如
/public/key.pem)不走 upstream →$upstream_addr为空,$request_length仍有效但不代表发往上层,建议用if ($upstream_addr = "") { ... }过滤或在日志中显式标注"type=static"
不复杂但容易忽略:Nginx 没有 $upstream_bytes_sent,但 $request_length 就是你需要的上游请求吞吐真相。用好它,再配上路径隔离和 TLS 上下文,就能真正看清每条安全链路的数据脉搏。











