
你的Nginx日志长这样:192.168.1.1 - - [27/Jul/2026:14:30:25 +0800] "GET /index.html HTTP/1.1" 200 15234。这是默认的combined格式,记录了IP、时间、请求方法、状态码、响应大小。看起来够用了。直到你想知道“这个请求到底花了多长时间”,或者“用户真实IP是什么”。默认日志回答不了这些问题。你需要的字段不在里面,因为默认的日志格式没有记录它们。
默认日志解决的是“谁访问了”,定制日志解决的是“访问过程怎么样”。
默认格式缺什么
Nginx默认的combined格式只记录请求的开始时间、HTTP方法、状态码、响应体大小。它不记录请求的处理时长,也不记录上游服务器的响应时间。当用户说“网站慢”时,你无法从默认日志中确认慢在哪一环——是Nginx处理慢,还是PHP-FPM执行慢,还是数据库响应慢。你只能凭猜测去排查。
默认格式记录的客户端IP可能是CDN节点或负载均衡器的IP,而不是真实用户的IP。如果你的网站使用了CDN或七层负载均衡,日志中的$remote_addr记录的是最后一跳的IP,而不是访问者的真实IP。这两个缺失的信息,在故障排查和运营分析中恰恰是最需要的。
定制日志格式:log_format
Nginx通过log_format指令定义日志格式。将以下配置添加到http块中:
nginx
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
}
main是格式名称,在access_log指令中引用。$remote_addr记录直接连接的客户端IP。$remote_user记录基本认证用户名。$time_local记录请求时间。$request记录完整请求行(方法+路径+协议)。$status记录响应状态码。$body_bytes_sent记录响应体大小。$http_referer记录来源页面。$http_user_agent记录客户端标识。$http_x_forwarded_for记录原始客户端IP(需代理传递)。
添加响应时间字段
响应时间是排查性能问题的关键字段。Nginx提供两个变量来记录时间:
$request_time:从接收客户端第一个字节到发送完最后一个字节的总耗时,包括接收请求、处理请求、发送响应三个环节。对应变量为$request_time,单位为秒,精度到毫秒。
$upstream_response_time:Nginx转发请求到上游服务器(如PHP-FPM、Tomcat)后,等待并接收完整响应所花费的时间。不包括Nginx自身的处理时间。
在日志格式中添加这两个字段:
nginx
log_format timing '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time ut="$upstream_response_time"';
rt标记总响应时间,ut标记上游响应时间。当rt接近ut时,说明Nginx本身处理快,慢在上游服务。当rt远大于ut时,说明慢在Nginx层(可能是网络传输慢,也可能是客户端网络慢)。
记录真实客户端IP
当网站使用CDN或七层负载均衡时,$remote_addr记录的是CDN节点或负载均衡的IP,而不是访问者的真实IP。CDN和负载均衡器通常会在HTTP头中传递原始客户端IP。对于Cloudflare,使用$http_cf_connecting_ip;对于通用CDN或代理,使用$http_x_forwarded_for。
在http块中添加以下配置,让Nginx从正确的位置获取客户端IP:
nginx
http {
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}
不同场景的日志格式推荐
| 场景 | 推荐字段 | 用途 |
|---|---|---|
| 运维排查 | $remote_addr、$request、$status、$request_time、$upstream_response_time | 定位性能瓶颈 |
| 安全分析 | $remote_addr、$request、$status、$http_user_agent、$http_x_forwarded_for | 识别异常请求 |
| 数据分析 | $request、$status、$http_referer、$http_user_agent | 用户行为分析 |
一个真实案例
某电商平台在促销活动中发现部分用户打开商品页很慢。Nginx默认日志只显示状态码200和响应大小,看不出耗时。添加$request_time和$upstream_response_time后,发现$upstream_response_time平均8秒,而$request_time平均8.5秒——慢在PHP-FPM处理环节,而不是网络或Nginx。针对商品详情接口优化代码和缓存后,$upstream_response_time降到0.2秒。
最后一句
Nginx默认日志只能告诉你“有人访问了”,定制日志能告诉你“访问过程怎么样”。默认日志记录的是谁来了,定制日志告诉你他等待了多久、慢在哪个环节。响应时间和真实IP这两个字段,在故障排查和运营分析中比默认字段更有价值。去检查你的Nginx日志格式,把$request_time和$upstream_response_time加进去,下次用户说“网站慢”时,你的日志里已经有答案了。




