nginx access_log 在极限压测下确实会成为性能瓶颈,关键在于日志写入拖慢请求处理、触发磁盘i/o阻塞及缓冲区被击穿导致同步落盘,需从内核缓冲、模块行为和系统资源三方面实测验证。

看 access_log 缓冲是否真正启用
确认配置中已显式开启缓冲,且未被隐式禁用:
- 必须带 buffer=size 参数,例如:
access_log /var/log/nginx/access.log main buffer=64k flush=5s; - 不能与
gzip或syslog同时使用——这两者会强制关闭缓冲,日志直写 - 若使用
if条件记录(如access_log ... if=$loggable;),缓冲也会失效,改用 map 预计算更稳妥
压测中监控日志路径的 I/O 压力
缓冲有效时,磁盘写入应呈「低频批量」特征;若变成高频小写,则说明缓冲未生效或被快速填满:
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
- 用
iostat -x 1观察日志所在磁盘的 await(平均I/O等待时间)和 %util:持续 >80% 或 await >20ms 就是瓶颈信号 - 用
pidstat -d -p $(pgrep nginx) 1查看 worker 进程的每秒读写字节数(kB_rd/s、kB_wr/s):若 kB_wr/s 突然飙升且与 QPS 强相关,说明缓冲被绕过 - 对比开启/关闭 buffer 后的
cat /proc/$(pgrep nginx)/io | grep write_bytes累计值:缓冲开启后,write_bytes 增速应明显放缓
检查日志写入是否阻塞事件循环
真正影响吞吐的是日志写入是否让 worker 进程卡在 sys_write 上:
- 用
strace -p $(pgrep nginx) -e write -s 100 -T 2>&1 | grep 'write.*access'抽样抓取写日志系统调用耗时:单次 >1ms 即危险,>5ms 表示已严重拖累 - 结合
nginx -t && nginx -s reload后观察ab或wrk的 RPS 是否骤降:若 reload 后吞吐下降 15%+,大概率是新日志配置触发了同步写 - 启用
error_log /var/log/nginx/error.log notice;并压测,搜索日志中是否出现 "could not open file"、"Permission denied" 或反复 "open() failed":权限或 inotify 句柄不足会导致 fallback 到同步写
配套验证:避免误判为日志问题
很多“日志慢”其实是其他层问题被归因错误:
- 确保
client_body_buffer_size和client_max_body_size足够大,否则大请求体落盘会抢占磁盘 I/O,连带拖慢日志 - 检查
access_log路径所在文件系统是否为 ext4/xfs,且挂载选项含 noatime,data=ordered;避免用 NFS 或加密盘存日志 - 若用 logrotate,确认没在压测中触发
kill -USR1:该信号会强制刷盘并重开文件,造成瞬时阻塞










