ngx_event_timer_resolution控制nginx定时器最小精度,单位毫秒,通过调整epoll_wait超时值影响唤醒频率;设为0时永久阻塞,设为10ms则每10ms强制唤醒检查定时器,过小会显著增加CPU开销和调度压力。

nginx 的 ngx_event_timer_resolution(常被简写为 ngx_event_timer_res)控制事件模块中定时器的最小精度,它不直接“调整内核”,但会显著改变 nginx 与内核 timer 机制的交互方式,进而影响 CPU 占用、延迟响应和系统负载。理解其原理和副作用,比盲目调小更重要。
timer_resolution 是什么?它不等于 setitimer 或 clock_gettime
该配置项(单位为毫秒)告诉 nginx:不必每毫秒都检查一次超时,而是允许将多个定时器“合并”到最近的同一时刻触发,前提是误差不超过设定值。底层依赖的是 epoll/kqueue 的超时参数(epoll_wait 的 timeout 或 kqueue 的 kevent 超时),而非独立的 POSIX timer 或 timerfd。
例如:
- 设为 0(默认):nginx 每次进入 epoll_wait 都传入 -1(永久阻塞),仅当有 I/O 事件或信号才唤醒;定时器检查只在每次事件循环开始/结束时做一次粗略扫描。
- 设为 10ms:nginx 保证定时器误差 ≤10ms,因此每次调用 epoll_wait 最多等待 10ms,即使无 I/O 也会定期唤醒,以检查到期定时器(如 keepalive 超时、resolver 超时等)。
设小了会怎样?CPU 和内核调度压力明显上升
将 timer_resolution 设为 1ms 或 5ms,看似提升了定时精度,实则带来三重开销:
-
频繁系统调用:每毫秒一次
epoll_wait(timeout=1),导致上下文切换剧增,尤其在空载或低并发时,CPU 大量时间花在内核态进出上; -
干扰内核 CFS 调度:短周期唤醒使 nginx worker 进程持续处于
R(运行)或S(可中断睡眠)状态切换中,降低调度器对长周期任务的友好性,可能挤压其他进程的 CPU 时间片; - 虚假 wakeups 增加:即使无真实事件,内核仍需按期唤醒进程,触发不必要的事件循环、红黑树遍历和回调执行,浪费 cache line 和分支预测资源。
哪些场景真需要调小?别为“感觉快”而改
绝大多数 HTTP 服务完全不需要 sub-10ms 定时精度。真正受益的场景极少,且必须满足两个条件:高频率、强时效性、用户态主动管理的定时行为 + 内核无法替代。
-
自定义 upstream health check 的亚秒级探测(如每 200ms 发心跳包),且不能依赖
upstream_check_module等已优化的扩展; - 实时流代理中极低延迟的 buffer flush 控制(如 WebRTC 转发层需严格控制 jitter buffer 触发时机);
- 与硬件设备驱动协同的确定性 I/O 调度(如 nginx 作为边缘网关对接 FPGA 加速卡,需精确对齐硬件 timer 中断)。
注意:keepalive timeout、client_header_timeout 等常规超时字段本身不受 timer_resolution 影响——它们由事件循环中定时器红黑树的插入逻辑决定,只要事件循环能定期运行即可,不一定非要靠高频 epoll 唤醒。
更优替代方案:用内核能力代替用户态轮询
若确实需要高精度定时,优先考虑绕过 nginx 自身 timer 机制:
-
用
timerfd_create+epoll_ctl注册专用定时器 fd:在自定义模块中创建纳秒级精度的单次/周期 timer,由内核精确触发,不干扰主事件循环; -
启用
SO_BUSY_POLL或AF_XDP:减少网络栈延迟,让请求更快到达 nginx,从而降低对“快速响应定时器”的依赖; -
用
io_uring替代 epoll(需 patch 或使用 OpenResty 1.25+):支持带超时的异步等待,内核完成 timer + I/O 复合操作,避免用户态频繁唤醒。
这些方法把精度控制交给内核,既满足需求,又不牺牲整体效率。










