Nginx定时器是嵌入事件循环的轻量级调度单元,基于全局最小堆管理,毫秒级精度同步触发超时回调;其epoll_wait超时动态联动最近定时器,与连接状态强绑定且可随时取消。

Nginx 的定时器不是独立线程或后台守护进程,而是深度嵌入事件循环的轻量级调度单元。它不靠轮询、不发信号、不唤醒线程,所有超时动作(读超时、写超时、keepalive 超时、proxy timeout 等)都由主事件循环统一驱动,在毫秒级精度下高效触发。
定时器统一挂载在最小堆上
Nginx 使用一个全局最小堆(min-heap)管理所有活跃定时器节点。每个节点只存两个关键字段:到期时间戳(毫秒级绝对值)和回调函数指针。插入、删除、查找最近到期项的时间复杂度均为 O(log n),适合海量短连接场景下的高频增删。
- 新连接建立或 upstream 请求发起时,调用 ngx_add_timer() 将其读/写超时注册进堆
- 若请求提前完成(如数据收齐、响应发完),立刻调用 ngx_del_timer() 移除对应节点,避免误触发
- 堆中无冗余状态,不绑定连接生命周期外的上下文,内存开销极低
定时器检查与事件处理严格同步
每次事件循环迭代开始前,Nginx 都会执行 ngx_event_expire_timers(),扫描并触发所有已到期的定时器回调。这个过程完全同步、无抢占、无中断,与 socket 事件处理共享同一执行流。
- epoll_wait 返回后,不直接处理就绪 fd,而是先过一遍定时器堆
- 超时回调函数(如 ngx_http_set_keepalive、ngx_http_finalize_request)被立即同步调用
- 没有“定时器线程”或“超时队列”,所有逻辑都在当前 worker 的单一线程内完成
epoll_wait 超时时间动态联动定时器
epoll_wait 的阻塞时长不是固定值,而是取自定时器堆中最近一个到期时间与当前时间的差值。这使得事件循环既能及时响应网络 I/O,又能准时执行清理任务。
- 若 500ms 后有个 keepalive 连接要关闭,epoll_wait 最多只等 500ms
- 若有就绪事件,epoll_wait 立即返回,不等待超时;若无就绪但有临近定时器,也快速返回以执行清理
- 仅当既无就绪事件、也无待触发定时器时,才进入轻量休眠,CPU 占用趋近于零
定时器与连接状态强绑定、可取消
每个连接的超时控制并非独立倒计时器,而是通过 ngx_connection_t 中关联的 ngx_event_t 结构实现声明式调度。该事件对象可随时取消,确保语义准确。
- 客户端读超时的 timer 回调是 “关闭连接” 或 “转入 keepalive 等待状态”
- upstream 写超时的 timer 回调可能是 “标记后端失败” 或 “切换节点重试”
- 所有 timer 都可被业务逻辑主动注销,例如收到完整请求体后立即删掉读超时



















