排查网站加载速度问题时,日志里最该先核对的是时间字段,而不是状态码或User-Agent。一个常见误解是:只要日志里出现大量200状态码,就说明服务器响应正常、慢在别处。实际上200只表示请求最终成功,完全不反映耗时。如果日志没有记录请求开始时间、响应结束时间和各阶段耗时,你只能看到“成功”,看不到“慢在哪”。正确做法是先确认日志格式里有哪些时间字段,再按阶段拆分定位。
不同服务器和中间件的默认日志格式差异很大,先看原始日志行里有没有这些内容:
$request_time:Nginx中从读取客户端第一个字节到发送完响应的总耗时,单位秒,通常带小数。$upstream_response_time:反向代理到后端应用的耗时。它和总耗时的差值,就是网络传输与Nginx自身处理的部分。%D或%T:请求处理耗时,单位分别是微秒和秒。如果日志里只有$time_local这类时间戳,没有耗时字段,那它只能用于统计请求量和错误分布,无法直接定位单次慢请求。这时需要先调整日志格式,把耗时字段加上,再复现问题。判断依据很简单:同一秒内出现多条请求时,没有耗时字段就无法区分哪条慢。
拿到$request_time和$upstream_response_time后,按下面的条件判断:
0.1, 2.3):说明请求经过了多次上游转发,需要结合重试或负载均衡配置一起看。-:该请求没有走到上游,可能是静态文件直接返回,也可能是被限流或拒绝。这里要注意,$upstream_response_time为-并不等于请求失败,它只说明没有上游参与。把这一点和状态码结合看,才能区分“静态资源慢”和“后端慢”。
单条日志往往不够,需要用请求标识把同一请求在Nginx、应用、数据库各层的记录关联起来。核对以下字段:
$request_id或应用生成的trace ID):确认各层日志是否使用同一个标识。$body_bytes_sent):大响应体在慢网络下会显著拉长总耗时,即使上游很快。如果日志里没有请求ID,跨层排查会非常困难。此时可以先在应用层补充生成并透传请求ID,再复现问题。
假设你怀疑某个页面加载慢,按下面步骤操作:
$request_time降序排列,取最慢的若干条。$upstream_response_time,判断慢在Nginx侧还是应用侧。这套顺序的适用条件是日志中已有耗时字段或可以补充埋点。如果日志格式暂时无法修改,只能先做请求量、状态码和响应体大小的统计,无法精确定位耗时来源。
下一步,先打开一份真实的访问日志,确认其中是否包含总耗时和上游耗时字段;如果没有,就从调整日志格式开始,再重新收集一轮数据。