Nginx超时机制是事件循环的自然延伸,非独立线程;所有超时节点注册于worker进程的红黑树,由ngx_process_events_and_timers统一调度,精度毫秒级;定时器必须绑定ngx_event_t,一次性执行且需手动清理;不适用于业务层高频、跨进程或复杂调度任务。

Nginx 的异步事件驱动架构并不把“超时定时任务”当作通用调度任务来处理,它只管理与网络 I/O 生命周期强绑定的轻量级超时事件,比如连接空闲、请求头读取、响应发送等。它的核心不是启动一堆独立倒计时器,而是把所有超时判断统一收口到事件循环中,靠红黑树 + 事件引擎协同完成毫秒级精度的非阻塞控制。
超时不是独立线程,而是事件循环的自然延伸
Nginx 每个 worker 进程运行一个独立的事件循环,所有超时节点(如 ngx_event_t)都注册进本 worker 的全局红黑树 ngx_event_timer_rbtree。这个树按到期时间排序,插入、删除、查找都是 O(log n)。事件循环主函数 ngx_process_events_and_timers 每次迭代前,先调用 ngx_event_find_timer() 获取最近超时时间,再把这个值作为 epoll_wait 的 timeout 参数——这样既避免轮询,又确保不漏掉任何到期动作。
超时对象必须依附于具体事件,不能脱离上下文存在
每个定时器必须绑定到一个 ngx_event_t 实例(比如某个连接的读事件 rev 或写事件 wev),通过 ngx_add_timer(ev, msec) 注册,由 Nginx 自动计算绝对到期时间并插入红黑树。超时触发时,回调函数在主线程同步执行,因此:
- 回调里不能做耗时操作(如文件读写、复杂计算),否则会卡住整个 worker
- 必须手动调用
ngx_del_timer(ev)清理,尤其在连接关闭或请求结束前,否则可能访问已释放内存 - 定时器没有重试、优先级、延迟补偿等机制,只是一次性“到期即执行”
配置指令背后都是自动注册的连接级超时
你写的 client_header_timeout 60s 或 proxy_read_timeout 30s,并不是启动新定时器,而是为对应阶段的连接/请求设置阈值,Nginx 在进入该阶段时自动调用 ngx_add_timer() 绑定超时逻辑。例如:
- 请求头未在 60 秒内收完 → 触发
ngx_http_finalize_request并返回 408 - upstream 响应 30 秒没回来 → 关闭后端连接、标记失败、尝试重试(若配置了
proxy_next_upstream) - keepalive 连接空闲满 65 秒 → 执行
ngx_http_set_keepalive,回收连接资源
不适合做业务层定时任务的原因很明确
- 没有任务队列,无法堆积大量待执行任务
- 不支持高频触发(如每秒万次),红黑树节点开销和主线程串行执行是瓶颈
- 无法跨进程协调,每个 worker 的定时器完全隔离
- 超时精度依赖系统时钟和
epoll_wait返回时机,不是严格实时
如果真需要延时调度类能力(比如清理缓存、触发通知),推荐方式是:用共享内存存任务元数据,再让某个 worker 周期性(如每 200ms)用 ngx_add_timer() 注册扫描任务,在回调里遍历共享内存中到期项并分发——这是间接适配,而非直接使用 Nginx 定时器。



















