
1 定义ngx_event_add_timer 函数 定义在 ./nginx-1.24.0/src/event/ngx_event_timer.hstaticngx_inlinevoidngx_event_add_timer(ngx_event_t*ev,ngx_msec_ttimer){ngx_msec_tkey;ngx_msec_int_tdiff;keyngx_current_msectimer;if(ev-timer_set){/* * Use a previous timer value if difference between it and a new * value is less than NGX_TIMER_LAZY_DELAY milliseconds: this allows * to minimize the rbtree operations for fast connections. */diff(ngx_msec_int_t)(key-ev-timer.key);if(ngx_abs(diff)NGX_TIMER_LAZY_DELAY){ngx_log_debug3(NGX_LOG_DEBUG_EVENT,ev-log,0,event timer: %d, old: %M, new: %M,ngx_event_ident(ev-data),ev-timer.key,key);return;}ngx_del_timer(ev);}ev-timer.keykey;ngx_log_debug3(NGX_LOG_DEBUG_EVENT,ev-log,0,event timer add: %d: %M:%M,ngx_event_ident(ev-data),timer,ev-timer.key);ngx_rbtree_insert(ngx_event_timer_rbtree,ev-timer);ev-timer_set1;}ngx_event_add_timer 函数用于 为事件添加或更新超时定时器并将定时器节点插入全局红黑树中。 为了优化高并发下快速连接的重复更新它采用惰性策略 若事件已有定时器且新旧到期时间差小于 NGX_TIMER_LAZY_DELAY 则直接复用旧定时器避免不必要的红黑树删除与插入操作从而降低 CPU 开销。2 详解1 函数签名staticngx_inlinevoidngx_event_add_timer(ngx_event_t*ev,ngx_msec_ttimer)无返回值参数 1 ngx_event_t *ev 当前需要添加定时器的事件 参数 2 ngx_msec_t timer 超时时间单位是毫秒 从“现在”开始计时。2 逻辑流程1 局部变量 2 计算到期时间 3 已有定时器 4 插入定时器1 局部变量{ngx_msec_tkey;ngx_msec_int_tdiff;2 计算到期时间keyngx_current_msectimer;计算事件应该超时的绝对时间。 ngx_current_msec 是全局变量 在每次事件循环迭代开始时被更新为当前系统毫秒时间。 将相对超时 timer 加上当前时间 得到到期时刻 key。 这样定时器只需与一组全局递增的时间戳比较 而无需倒计时极大简化了超时检测逻辑。3 已有定时器if(ev-timer_set){/* * Use a previous timer value if difference between it and a new * value is less than NGX_TIMER_LAZY_DELAY milliseconds: this allows * to minimize the rbtree operations for fast connections. */diff(ngx_msec_int_t)(key-ev-timer.key);if(ngx_abs(diff)NGX_TIMER_LAZY_DELAY){ngx_log_debug3(NGX_LOG_DEBUG_EVENT,ev-log,0,event timer: %d, old: %M, new: %M,ngx_event_ident(ev-data),ev-timer.key,key);return;}ngx_del_timer(ev);}检查该事件当前是否已有定时器存在于红黑树中。 ev-timer_set 是一个布尔标志 为真表示定时器节点已在全局定时器红黑树内。 若已存在则进入更新路径需要决定是否修改 否则直接跳到插入逻辑。这构成了惰性更新的前置判断。计算新到期时间 key 与旧到期时间 ev-timer.key 的有符号差值。 减法产生无符号结果再显式转换为有符号型 ngx_msec_int_t。 这一步将环绕差值转化为数学上的真实差值例如 1 - 10 -9 而不是极大的正数 确保后续比较的准确性。 判断新旧到期时间的绝对差是否在惰性延迟阈值内。 ngx_abs(diff) 取绝对值忽略方向只关心变化幅度。 NGX_TIMER_LAZY_DELAY 是一个编译期常量通常 1~2 毫秒。 若差值小于该值则认为定时器“足够接近”无需真正更新。从全局红黑树中删除该事件现有的定时器节点。 当新旧差值超出允许的惰性范围意味着必须更新超时时间。 需要先将旧节点从树中移除再插入新节点。 ngx_del_timer 内部会调用 ngx_rbtree_delete 并可能将 timer_set 置零具体依赖实现为重新插入做准备。4 插入定时器ev-timer.keykey;ngx_log_debug3(NGX_LOG_DEBUG_EVENT,ev-log,0,event timer add: %d: %M:%M,ngx_event_ident(ev-data),timer,ev-timer.key);ngx_rbtree_insert(ngx_event_timer_rbtree,ev-timer);ev-timer_set1;}将新计算的绝对到期时间赋值给事件内部的定时器节点。 将事件的定时器节点插入到全局定时器红黑树中。 将事件的定时器标记为“已设置”。