当前位置: 首页 > news >正文

ngx_process_events_and_timers

1 定义

ngx_process_events_and_timers 函数 定义在 ./nginx-1.24.0/src/event/ngx_event.c
voidngx_process_events_and_timers(ngx_cycle_t*cycle){ngx_uint_tflags;ngx_msec_ttimer,delta;if(ngx_timer_resolution){timer=NGX_TIMER_INFINITE;flags=0;}else{timer=ngx_event_find_timer();flags=NGX_UPDATE_TIME;#if(NGX_WIN32)/* handle signals from master in case of network inactivity */if(timer==NGX_TIMER_INFINITE||timer>500){timer=500;}#endif}if(ngx_use_accept_mutex){if(ngx_accept_disabled>0){ngx_accept_disabled--;}else{if(ngx_trylock_accept_mutex(cycle)==NGX_ERROR){return;}if(ngx_accept_mutex_held){flags|=NGX_POST_EVENTS;}else{if(timer==NGX_TIMER_INFINITE||timer>ngx_accept_mutex_delay){timer=ngx_accept_mutex_delay;}}}}if(!ngx_queue_empty(&ngx_posted_next_events)){ngx_event_move_posted_next(cycle);timer=0;}delta=ngx_current_msec;(void)ngx_process_events(cycle,timer,flags);delta=ngx_current_msec-delta;ngx_log_debug1(NGX_LOG_DEBUG_EVENT,cycle->log,0,"timer delta: %M",delta);ngx_event_process_posted(cycle,&ngx_posted_accept_events);if(ngx_accept_mutex_held){ngx_shmtx_unlock(&ngx_accept_mutex);}ngx_event_expire_timers();ngx_event_process_posted(cycle,&ngx_posted_events);}
ngx_process_events_and_timers 函数 在每个 worker 进程的主循环中被反复调用。 它负责在一次迭代中协调完成: 根据定时器计算下次 I/O 等待的超时时间、参与 accept 互斥锁争用、调用事件模块等待网络事件、 处理延迟的 accept 事件(新连接)、释放锁、触发到期的定时器,最后处理其他延迟的 I/O 读写事件。 通过严格的顺序控制和延迟执行机制,它在保证高并发响应的同时,将 accept 锁持有时间降到最低。

2 详解

1 函数签名

voidngx_process_events_and_timers(ngx_cycle_t*cycle)
返回类型:void 该函数不返回任何值。
参数 ngx_cycle_t *cycle 指向当前运行周期的上下文

2 逻辑流程

1 局部变量 2 确定超时时间与标志位 3 Accept 互斥锁 4 处理上一轮遗留的“下轮事件” 5 调用底层事件模块收集 I/O 事件 6 处理延迟的 accept 事件 7 释放 Accept 锁 8 触发所有到期的定时器 9 处理普通延迟 I/O 事件

1 局部变量
{ngx_uint_tflags;ngx_msec_ttimer,delta;

2 确定超时时间与标志位
if(ngx_timer_resolution){timer=NGX_TIMER_INFINITE;flags=0;}else{timer=ngx_event_find_timer();flags=NGX_UPDATE_TIME;#if(NGX_WIN32)/* handle signals from master in case of network inactivity */if(timer==NGX_TIMER_INFINITE||timer>500){timer=500;}#endif}
#1 检查是否配置了 timer_resolution 指令(使用系统定时信号 setitimer 周期性更新时间)。 逻辑:若该值非零,说明时间由信号驱动更新,无需事件循环自己维护时间缓存。 意义:两种时间机制的切换分支。
#1-1 将超时设为无限,标志清零。 逻辑:信号会周期性地中断事件循环,更新 ngx_current_msec,无需因定时器而主动唤醒。
#2 进入另一种时间维护模式(默认)
#2-1 调用 ngx_event_find_timer() 查找红黑树中最近到期的定时器,返回距当前时间的毫秒数; 同时设置 NGX_UPDATE_TIME 标志。 逻辑: 红黑树中每个定时器对应未来某个时刻触发, 函数返回最近触发点与现在的差值。 NGX_UPDATE_TIME 告诉底层事件模块, 系统调用返回后要立即调用 ngx_time_update() 更新缓存时间。 意义:让 epoll_wait 精确阻塞到最近定时器到期为止,避免过早唤醒浪费 CPU。
#2-2 Windows 平台特殊处理,强制将超时限制在 500ms 以内

3 Accept 互斥锁
if(ngx_use_accept_mutex){if(ngx_accept_disabled>0){ngx_accept_disabled--;}else{if(ngx_trylock_accept_mutex(cycle)==NGX_ERROR){return;}if(ngx_accept_mutex_held){flags|=NGX_POST_EVENTS;}else{if(timer==NGX_TIMER_INFINITE||timer>ngx_accept_mutex_delay){timer=ngx_accept_mutex_delay;}}}}
#1 处理 accept 互斥锁(多 worker 负载均衡) 判断是否启用了 accept_mutex 机制
#2 当前 worker 被标记为“暂时停止竞争锁”,则将禁止计数器减 1,然后跳过本次锁竞争 ngx_accept_disabled 是一个全局变量, 当本 worker 连接数达到 ngx_accept_disabled_threshold 时会被设为某个正值, 逐次递减直至 0,期间不再参与争锁。 意义:实现简易的负载均衡,让过载的 worker 逐渐让出新连接到其他 worker。
#3-1 否则,尝试获取 accept 锁 非阻塞地尝试获取共享内存中的互斥锁; 若返回 NGX_ERROR(通常标志共享内存损坏),直接退出整个函数。 逻辑:锁操作本身失败通常意味着严重错误,应尽快返回,使上层主循环检查并处理进程终止。 意义:快速故障隔离,避免在异常状态下继续运行。
#3-2 成功持锁后,将 NGX_POST_EVENTS 标志加入 flags。 逻辑: 该标志指示底层事件模块, 将所有到达的事件(包括新连接和普通 I/O 事件)先放入延迟队列, 而不立即执行其回调。 意义:缩短持有 accept 锁的时间,避免在处理事件回调过程中长期占用锁。
#3-3 若未获得锁,则限制本次事件等待的超时时间。 如果 timer 为无限或大于 ngx_accept_mutex_delay(通常 500ms), 强制将其缩减为该值。 这样未获得锁的 worker 最多睡眠此段时间,之后醒来再次尝试争锁。 意义:避免长时间拿不到锁的 worker 一直阻塞,导致无法及时响应新连接分发。

4 处理上一轮遗留的“下轮事件”
if(!ngx_queue_empty(&ngx_posted_next_events)){ngx_event_move_posted_next(cycle);timer=0;}
处理上一轮延迟的“下轮事件” 检查队列 ngx_posted_next_events 是否非空, 若有事件,则将它们移动到当前待处理队列,并将 timer 置 0。 意义:保证高优先级延迟事件不被阻塞的 I/O 等待耽误。

5 调用底层事件模块收集 I/O 事件
delta=ngx_current_msec;
记录开始等待前的时间戳
(void)ngx_process_events(cycle,timer,flags);
调用具体事件模块的 process_events(如 ngx_epoll_process_events) 传递 timer 作为最大阻塞时间(毫秒)。 传递 flags 控制行为(如是否更新时间、是否延迟执行事件)。 返回值被显式转换为 void 忽略,因为所有事件已通过队列或回调函数处理。 意义:这是进程阻塞、等待 I/O 事件的唯一位置,是事件循环的“心脏”调用。

delta=ngx_current_msec-delta;
计算实际等待的毫秒数。 ngx_current_msec 此时已更新(如果 flag 包含 NGX_UPDATE_TIME), 差值即为 epoll_wait 等函数消耗的时间。

ngx_log_debug1(NGX_LOG_DEBUG_EVENT,cycle->log,0,"timer delta: %M",delta);
在 debug 日志级别下,输出本循环的等待耗时

6 处理延迟的 accept 事件
ngx_event_process_posted(cycle,&ngx_posted_accept_events);

7 释放 Accept 锁
if(ngx_accept_mutex_held){ngx_shmtx_unlock(&ngx_accept_mutex);}
如果本轮持有了 accept 互斥锁,现在解锁

8 触发所有到期的定时器
ngx_event_expire_timers();
遍历红黑树,找出所有到期的定时器事件并执行其回调。

9 处理普通延迟 I/O 事件
ngx_event_process_posted(cycle,&ngx_posted_events);}
处理所有因 NGX_POST_EVENTS 而延迟的普通读写事件。 这些事件已与 accept 锁无关,因此在释放锁后处理,可避免阻塞其他 worker 竞争新连接。 意义:在非关键路径上完成大工作量的数据处理,实现高效解锁后的并行工作。

总结 该函数通过精心安排的顺序和延迟队列,将一次事件循环切分为: 定时器感知 → 锁竞争 → 事件等待 → 新连接处理 → 解锁 → 定时器触发 → 普通 I/O 处理 这种流水线设计保证了锁持有时间极短、高优先级事件及时响应、所有事件一次性处理, 最终成就了 Nginx 的高并发低延迟特性。
http://www.jsqmd.com/news/722779/

相关文章:

  • Zotero插件生态深度体验:除了Zotero-GPT,还有哪些AI工具能帮你读论文、写笔记?
  • 如何用5分钟完成华硕笔记本终极性能调校:免费硬件控制工具完整指南
  • 挖到一个好用的双语字幕插件
  • 第97篇:联邦学习原理与应用——如何在保护隐私的前提下协同训练AI?(原理解析)
  • DreamOmni3:涂鸦与多模态生成的创意融合
  • 螺旋风管的生产工艺与技术要点解析
  • Dev Containers 成本黑洞排查指南(附真实trace日志+Prometheus监控模板):你的devcontainer.json正悄悄烧钱!
  • KLayout开源版图工具:芯片设计新手的终极入门指南
  • 如何让谷歌快速收录网站? 进驻谷歌新闻,文章3秒被收录的准入细则
  • 机器学习泛化理论:Hoeffding不等式与Occam边界解析
  • ARM内存管理:MAIR寄存器原理与应用实践
  • 不只是扫一扫:用Python PIL库把二进制字符串‘画’成二维码的几种方法
  • 新概念英语第二册59_In or out
  • 别再手动配路由了!用Apisix数据编辑器YAML文件5分钟搞定API网关转发
  • 桌面软件 vs 微信小程序,视频转文字提取怎么操作?2026年视频转文字工具推荐
  • 社交媒体数据聚合CLI工具设计与实现:从抽象层到自动化监控
  • 第98篇:AI在会展与活动行业的应用——智能策划、虚拟展厅与观众互动(操作教程)
  • 4-26联合训练 tmux
  • CTF解题技巧与漏洞利用实战
  • 新概念英语第二册60_The future
  • RePKG深度解析:解锁Wallpaper Engine资源宝库的专业工具
  • 别再手动改.condarc了!Anaconda配置管理保姆级教程(含清华/阿里源一键配置)
  • DIY实战|0.8寸WiFi自动授时电子钟,国产数码管驱动芯片方案分享
  • 灵魂摆渡没了灵魂,AI 电影只剩躯壳?看《第一大道》如何破局
  • Arm GICv3虚拟中断控制器架构与优化实践
  • 第99篇:AI+高端制造与工业互联网——数字孪生、工艺优化与无人车间(项目实战)
  • Pytorch:CNN进行图象分类案例
  • Waymo进驻波特兰:助力零交通事故愿景,减少严重伤害事故13倍!
  • 终极指南:3分钟掌握Semi-Utils批量水印处理神器
  • YOLO26-seg分割优化:注意力魔改 | 轻量级自注意力机制CoordAttention | CVPR2021