nginx访问日志“丢包”实为缓冲滞留后丢失,核心排查点是buffer过小(如默认8k)、flush过长、worker异常退出未清空缓冲;需检查access_log配置是否含合法buffer+flush组合、权限是否正确、重载是否误用reload而非usr1,并通过高并发测试与抓包比对验证。

检查 Nginx 访问日志丢包或不记录,核心是确认日志写入链路中缓冲区是否成为瓶颈——不是“丢包”而是“滞留后丢失”。重点看 buffer 大小是否过小、flush 时机是否过长、worker 进程异常退出时缓冲是否清空。
查当前 access_log 缓冲配置是否生效
打开 nginx.conf 或对应 server/location 块,定位 access_log 指令:
- 若只写
access_log /var/log/nginx/access.log;,则使用默认 buffer=8k(高并发下极易积压) - 若已配置,确认格式是否正确:如
access_log /var/log/nginx/access.log main buffer=64k flush=3s;—— 注意 buffer 和 flush 必须写在 format 名称之后、分号之前 - 运行
nginx -t验证语法;再用ps aux | grep nginx确认 worker 进程已加载新配置(必要时 reload)
验证缓冲是否实际起作用
仅看配置不够,要观察行为:
- 手动触发一次高并发请求(如用
ab -n 1000 -c 200 http://localhost/),然后立即执行:tail -n 20 /var/log/nginx/access.log
若日志延迟出现(比如等 3 秒以上才刷出),说明 flush 生效;若完全不出现,可能是权限问题或 buffer 被静默禁用 - 检查日志目录权限:
ls -ld /var/log/nginx和ls -l /var/log/nginx/access.log,确保 nginx worker 用户(如 www-data 或 nginx)有写权限 - 临时关闭缓冲测试:
access_log /var/log/nginx/access.log main buffer=1; flush=1ms;—— 若此时日志实时出现,基本锁定原缓冲策略不合理
排查缓冲导致的静默丢失场景
以下情况不会报错,但日志会永久消失:
-
worker 进程被 OOM killer 杀掉:缓冲区中未 flush 的日志直接丢失。查
dmesg -T | grep -i "killed process" - 用 systemctl reload 或 nginx -s reload 重载配置:会触发日志 reopen,但旧缓冲未强制刷盘就切换文件句柄。应只用 logrotate 发送 USR1 信号
-
error_log 未同步启用缓冲:当访问日志大量写入时,error_log 若仍为无缓冲直写,可能因 I/O 竞争加剧丢失。建议统一配:
error_log /var/log/nginx/error.log warn buffer=32k flush=2s;
辅助确认是否真丢日志
别只信采集端(如 Filebeat)或 ES 数据,从源头比对:
- 取最近 1 分钟内某固定路径的请求数:
grep '"GET /health" ' /var/log/nginx/access.log | awk -F'[' '{print $2}' | cut -d']' -f1 | date -f - +%s 2>/dev/null | awk '$1 > systime-60' | wc -l - 同时用 tcpdump 抓同时间段的包:
tcpdump -i lo port 80 -w /tmp/http.pcap && sleep 60 && pkill tcpdump,再统计 GET /health 包数 - 若原始日志条数明显少于抓包数,且排除了防火墙/代理拦截,则缓冲溢出或写入失败概率极高











