会,而且拖慢得挺明显。高并发下同步写日志导致磁盘i/o阻塞主线程,qps超50时响应延迟可从20ms升至300ms+,瓶颈在于文件锁争用、动态上下文重建和权限反复校验;解决需异步队列、精简日志、优化文件驱动及临时启用bufferhandler。

会,而且拖慢得挺明显。
高并发下每请求都同步写日志(比如用 Log::info() 写到 daily 文件),本质上是在主请求流程里做磁盘 I/O。一旦 QPS 超过 50,文件锁、权限检查、动态上下文重建这些开销就会快速放大——你可能看到整体响应延迟从 20ms 涨到 300ms+,监控里却只显示「应用变慢」,根本想不到是日志在卡。
关键瓶颈点有三个:
-
文件锁争用:默认
daily驱动开启'lock' => true,多进程抢flock(),strace 能看到大量F_SETLK等待 -
动态调用开销:
formatter里调Request::ip()或Request::fullUrl(),每次都要重建请求上下文,耗时堪比一次简单数据库查询 -
权限反复校验:设
'permission' => 0644且目录属主不匹配时,每次写日志都会触发chmod()系统调用
解决思路不是少记日志,而是把日志写入从请求主线程里剥离开:
- 改用异步队列处理:用 Redis 驱动队列,自定义
AsyncLogHandler把日志发到logs专用队列,由独立queue:work --queue=logs进程消费 - 日志内容精简:禁用 formatter 中的动态方法;时间格式用
'Y-m-d H:i:s';app.name、hostname这类静态值用static属性缓存 - 文件驱动优化:
daily通道必须设'lock' => false和'permission' => 0664,并加'max_files' => 30防止单日日志过大
如果只是调试阶段,也可以临时启用 Monolog 的 BufferHandler,内存里攒够 100 条再批量落盘,既减少 I/O 次数,又不改架构。
不复杂但容易忽略。











