同步写盘是nginx access_log造成显著延迟的主因,因worker进程需等待日志落盘;缓冲写入(buffer+flush)可缓解,异步syslog才是根本解法,且须物理层隔离io。

记录 access_log 本身会拖慢用户响应,但真正造成显著延迟的,是默认的同步写盘行为——Nginx worker 进程必须等日志数据真正落盘后才能继续处理下一个请求。高并发下,这个等待会堆积成队列,引发连锁反应:连接积压、超时激增、上游重试、CPU空转,最终触发雪崩。
同步刷盘是主因,不是“写日志”本身
access_log 默认每条请求都调用 write() + fsync(),直接命中磁盘 IO。尤其当磁盘繁忙(如与数据库共用 SATA 盘)、日志量大或小文件频繁写入时,单次落盘可能耗时数毫秒到上百毫秒。而 Nginx 是事件驱动模型,worker 进程一旦被阻塞,就无法服务其他请求。
- 现象典型:$request_time 明显升高,但 $upstream_response_time 基本稳定 → 问题在 Nginx 日志写入环节
- 验证方法:临时注释 access_log 行,压测对比延迟变化;或用 iostat -x 1 观察 %util 和 await 是否飙升
- 注意:error_log 不支持 buffer/flush,高频报错会加剧阻塞,应调高级别(如 warn)或转 syslog
缓冲写入(buffer + flush)是最简见效方案
让 Nginx 先把日志攒在内存里,达到阈值或超时再批量刷盘,大幅减少系统调用和磁盘寻道次数。
对设计或页面进行 WCAG 2.1 AA 无障碍审计。触发关键词:“audit accessibility”、 “check a11y”、 “is this accessible?” 或在审查设计时使用。
- 配置示例:
access_log /var/log/nginx/access.log main buffer=128k flush=3s; - 128KB 缓冲区适合中高流量场景,平衡丢志风险(宕机最多丢 128KB 日志)与性能提升
- flush=3s 防止低流量时日志长期滞留,3 秒是实时性与吞吐的常见折中点
异步解耦(syslog)才是根本解法
把日志写入完全移出主请求路径:Nginx 只需发 UDP/TCP 包给 rsyslog,不关心是否落盘、是否排队、是否失败。
- 配置示例:
access_log syslog:server=127.0.0.1:514,facility=local7,tag=nginx main; - rsyslog 必须启用磁盘辅助队列(disk-assisted queue),避免接收端卡住导致 Nginx 发送阻塞
- 优先用 TCP+RELP 协议,比 UDP 更可靠;避免 Unix socket,因启动顺序问题易连接失败
别忘了物理层隔离
即使上了缓冲或 syslog,如果日志落地磁盘和业务磁盘是同一块设备,IO 竞争依然存在。
- 将 /var/log 单独挂载到 NVMe 或 SSD,并加
noatime参数减少元数据写入 - rsyslog 的日志存储目录也必须放在该独立磁盘上
- NVMe 设备建议关闭调度器:
echo none > /sys/block/nvme0n1/queue/scheduler










