apache 反向代理需后端主动上报 x-response-time 响应头(如 java filter 中 setheader),apache 用 %{x-response-time}o 提取;配合 %d(代理自身耗时,单位微秒)对比可定位慢在代理层、后端或网络。

要在 Apache 反向代理中记录后端服务器的真实响应时间,核心是让 Apache 日志不仅能反映自身处理开销,还能捕获后端应用实际执行耗时——这必须由后端主动上报,Apache 仅负责接收并落盘。
用 %{X-Response-Time}o 捕获后端返回的耗时头
Apache 本身无法测量后端 Java/Tomcat/Go 等服务内部执行多久,只能靠后端在响应前写入标准响应头(如 X-Response-Time),单位为毫秒整数。Apache 通过 %{X-Response-Time}o(小写 o 表示 output header)提取该值:
- Java(Spring Boot)示例:在 Filter 中计算并设头:
response.setHeader("X-Response-Time", String.valueOf(durationMs)); - 确保头名完全一致、未被压缩模块(如 mod_deflate)或 WAF 拦截
- 若日志中该字段显示为 -,说明头未送达,需检查后端是否异常退出、异步逻辑未等待、或前置 Nginx 未透传(需配
proxy_pass_request_headers on)
搭配 %D 看清链路各段耗时
%D 是 Apache 自身从收到请求首字节到发出响应头的微秒耗时,它不含后端执行时间,但能反映代理层瓶颈(如 SSL 解密、重写规则、连接池等待):
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 定义日志格式时同时包含两者:
LogFormat "%h %l %u %t \"%r\" %>s %b %D %{X-Response-Time}o" proxy_rtt - 对比数值:若 %D 显著大于 X-Response-Time,说明慢在 Apache 层;若 X-Response-Time 远大于 %D,说明慢在后端;若两者都高且接近,可能是网络延迟或后端资源争用
- 注意:%D 为 0 或极小(如
增强诊断:加入代理状态与链路标识
单看耗时不够,还需上下文定位问题类型和归属:
- 添加 %{proxy-status}e(Apache 2.4.13+):显示底层代理结果,如
OK (http://10.0.1.5:8080)或ERR (timeout),可快速区分是后端宕机还是超时 - 若后端已集成 SkyWalking 或 Zipkin,让其注入 X-B3-TraceId,Apache 日志加
%{X-B3-TraceId}i,便于全链路日志关联 - 对 504 超时单独归档:用
SetEnvIfNoCase Status "^504" is_504+CustomLog logs/504-timeout.log ... env=is_504,避免被正常流量淹没
验证与排查常见空值原因
日志中 X-Response-Time 字段为空(-)不是配置失效,而是链路某环脱节:
- 后端未设置该头:curl -I 请求确认响应头是否存在
- 头名大小写不一致:HTTP 头名大小写敏感,
X-response-time≠X-Response-Time - mod_headers 未启用:
LoadModule headers_module modules/mod_headers.so必须加载 - 反向代理多跳场景:检查中间层(如 Nginx)是否过滤了自定义响应头










