nginx/事件循环

找出事件循环的下一次超时

nginx 事件定时器以到期时间为键放入红黑树,事件循环读取最小键确定等待上限。

release-1.26.3调度与资源分配核验 2026-10-08
相关概念

工程问题#

大量连接的读写超时会不断新增、取消和更新;事件循环需要快速定位最早到期的一批事件。

实际实现#

ngx_event_find_timer 调用 ngx_rbtree_min 得到最小到期时间;过期处理循环删除最小节点,再调用对应事件处理函数。

处理流程#

  1. 把事件按到期时间加入树
  2. 最小键减当前时间得到等待时长
  3. 唤醒后连续取出已到期节点
  4. 标记 timedout 并执行处理函数

源码片段#

固定版本 · 原文摘录
src/event/ngx_event_timer.crelease-1.26.3 · L32–L50
查看原文件
32ngx_msec_t33ngx_event_find_timer(void)34{35    ngx_msec_int_t      timer;36    ngx_rbtree_node_t  *node, *root, *sentinel;3738    if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {39        return NGX_TIMER_INFINITE;40    }4142    root = ngx_event_timer_rbtree.root;43    sentinel = ngx_event_timer_rbtree.sentinel;4445    node = ngx_rbtree_min(root, sentinel);4647    timer = (ngx_msec_int_t) (node->key - ngx_current_msec);4849    return (ngx_msec_t) (timer > 0 ? timer : 0);50}
ngx_event_find_timer

空树表示无限等待;非空时寻找红黑树最小键,计算距离当前毫秒时间的间隔,并把已经到期的结果钳制为零。这里返回事件循环的等待上限,不会直接执行定时器回调。

完整函数。此版本使用 ngx_rbtree_min 沿左子树查最小值,没有 Linux timerqueue 的最左节点缓存。

收益与取舍#

工程分析

带来的收益

  • 新增与删除具有对数级树操作成本
  • 支持任意事件的取消与重新登记

付出的代价

  • 工程分析:指针节点与旋转带来常数开销
  • 此实现查最小值需要沿树向左遍历

可比较的选择

有序链表头部即最近到期项,但插入可能线性扫描;QEMU 有可比较案例。

版本与适用范围#

对应 nginx 1.26.3 事件定时器;不是所有超时都需要独立的定时线程。

参考来源#

源码、官方文档与原始论文
01
nginx · ngx_event_find_timer / ngx_event_expire_timers

src/event/ngx_event_timer.c · ngx_event_find_timer / ngx_event_expire_timers

源码release-1.26.3

相关实现与比较#

4 个相关案例
11 个匹配案例