news 2026/5/15 16:54:34

ngx_worker_process_cycle

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ngx_worker_process_cycle

1 定义

ngx_worker_process_cycle 函数 定义在 ./nginx-1.24.0/src/os/unix/ngx_process_cycle.c
staticvoidngx_worker_process_cycle(ngx_cycle_t*cycle,void*data){ngx_int_tworker=(intptr_t)data;ngx_process=NGX_PROCESS_WORKER;ngx_worker=worker;ngx_worker_process_init(cycle,worker);ngx_setproctitle("worker process");for(;;){if(ngx_exiting){if(ngx_event_no_timers_left()==NGX_OK){ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"exiting");ngx_worker_process_exit(cycle);}}ngx_log_debug0(NGX_LOG_DEBUG_EVENT,cycle->log,0,"worker cycle");ngx_process_events_and_timers(cycle);if(ngx_terminate){ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"exiting");ngx_worker_process_exit(cycle);}if(ngx_quit){ngx_quit=0;ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"gracefully shutting down");ngx_setproctitle("worker process is shutting down");if(!ngx_exiting){ngx_exiting=1;ngx_set_shutdown_timer(cycle);ngx_close_listening_sockets(cycle);ngx_close_idle_connections(cycle);ngx_event_process_posted(cycle,&ngx_posted_events);}}if(ngx_reopen){ngx_reopen=0;ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"reopening logs");ngx_reopen_files(cycle,-1);}}}
ngx_worker_process_cycle 是 Nginx worker 进程的主循环函数, 核心作用如下: 初始化 worker 进程:设置进程身份、调用模块初始化、设置进程标题。 进入事件驱动循环: 反复调用 ngx_process_events_and_timers 处理网络 I/O 事件和定时器事件,是请求处理的核心驱动。 响应信号实现进程控制: SIGQUIT:触发优雅关闭(关闭监听、等待现有请求完成后再退出)。 SIGTERM:立即强制退出。 SIGUSR1:重新打开日志文件,支持日志轮转。 管理 worker 退出:在优雅关闭模式下,监测连接与定时器状态,确保安全退出。

2 详解

1 函数签名

staticvoidngx_worker_process_cycle(ngx_cycle_t*cycle,void*data)
返回值 函数不返回任何值 worker 进程的主循环是一个永不返回的无限循环(for (;;)), 只有在进程退出时才会通过调用 ngx_worker_process_exit() 等函数直接终止进程。 因此该函数不需要向调用者返回执行结果。
参数 ngx_cycle_t *cycle 指向当前运行周期上下文 void *data worker 进程的序号(从 0 开始),以 intptr_t 整数类型强制转换为 void* 传入 通过 void* 可以传递任意类型的数据(结构体指针、整数等),增强了接口的通用性

2 逻辑流程

1 局部变量 2 全局变量 3 初始化 4 修改进程标题 5 事件循环

1 局部变量
{ngx_int_tworker=(intptr_t)data;
从通用指针参数 data 中提取出 worker 进程的序号, 并赋值给局部变量 worker

2 全局变量
ngx_process=NGX_PROCESS_WORKER;ngx_worker=worker;
#1 设置全局变量 ngx_process 的值,标记当前进程的类型为 Worker NGX_PROCESS_MASTER:master 进程。 NGX_PROCESS_WORKER:worker 进程。 NGX_PROCESS_SINGLE:单进程模式。 #2 设置全局变量 ngx_worker 的值,保存当前 worker 的编号
为何需要同时设置类型和编号? 类型 (ngx_process):回答“我是哪类进程?”—— 宏观角色。 编号 (ngx_worker):回答“我是该类进程中的哪一个?”—— 微观实例。 二者结合完整描述了一个进程在整个 Nginx 多进程架构中的坐标

3 初始化
ngx_worker_process_init(cycle,worker);
Worker 进程启动后执行的第一个核心初始化函数。 它的作用是为 Worker 进程构建一个独立、完整且可运行的环境,使其能够处理请求。 如果没有这一步,Worker 进程就无法接入 Nginx 的事件驱动架构。

4 修改进程标题
ngx_setproctitle("worker process");
修改了进程在系统中显示的名称 提升可观测性 优化调试体验

5 事件循环
for(;;){
Worker 进程的事件循环主循环。 Worker 进程完成初始化后,便进入这个无限循环,它交替执行两大任务: 处理网络 I/O 与定时器事件,以及响应 Master 进程发来的信号指令。

if(ngx_exiting){if(ngx_event_no_timers_left()==NGX_OK){ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"exiting");ngx_worker_process_exit(cycle);}}
#1 检查全局标志位 ngx_exiting 是否为真 ngx_exiting 是整个优雅退出的总开关。一旦被置为 1, 意味着: 该 Worker 已经不再监听任何端口(ngx_close_listening_sockets 已执行)。 空闲连接已被主动关闭(ngx_close_idle_connections 已执行)。 当前正处于等待现有活跃连接自然结束的阶段。 循环位置的意义: 该检查放在每次事件循环的最开始, 保证了 Worker 在完成上一轮事件处理后, 会立即评估是否具备退出条件,避免不必要的阻塞等待。
#2 if (ngx_event_no_timers_left() == NGX_OK) 函数检查事件模块中维护的定时器红黑树是否为空 若定时器树为空(没有任何节点),返回 NGX_OK。 若定时器树中仍有节点(说明还有连接在等待超时事件),返回 NGX_ERROR。 定时器与连接的关系: 在 Nginx 中,几乎每一个活跃的连接都对应一个定时器事件。 退出条件判断逻辑:只有当定时器树彻底为空时,才能断定: 所有连接要么已被正常关闭,要么已因超时被处理完毕。 没有任何连接处于“等待未来某个时刻执行超时回调”的状态。 此刻退出进程完全安全,不会中断任何尚未完成的请求。
#3 日志记录与退出 ngx_log_error:在错误日志中写入 [notice] 级别的 "exiting" 消息。 运维人员可以通过日志确认 Worker 是正常优雅退出的,而非异常崩溃。 ngx_worker_process_exit(cycle): 执行 Worker 进程的最终退出动作:

ngx_log_debug0(NGX_LOG_DEBUG_EVENT,cycle->log,0,"worker cycle");
记录日志

ngx_process_events_and_timers(cycle);
Worker 进程主循环中的核心调度器, 它负责在一次循环迭代中,统一调度和分发网络 I/O 事件与定时器事件

if(ngx_terminate){ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"exiting");ngx_worker_process_exit(cycle);}
#1 if (ngx_terminate) ngx_terminate:全局整型标志变量,初始值为 0。 置位时机: 当 Worker 进程接收到 SIGTERM 或 SIGINT 信号时, 信号处理函数 ngx_signal_handler() 会将该标志置为 1。 检查时机: 每次事件循环完成一轮 I/O 和定时器处理后,立即检查该标志。
#2 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); 向 Nginx 错误日志文件写入一条 [notice] 级别的日志,内容为 exiting。 运维人员可通过日志确认 Worker 进程是由于收到 SIGTERM 而退出的,而非异常崩溃。
#3 ngx_worker_process_exit(cycle); 调用 Worker 进程的退出函数,执行以下关键步骤: 调用所有模块的 exit_process 回调函数,释放模块级资源。 销毁内存池 cycle->pool,归还所有分配的内存。 关闭所有打开的文件描述符。 最终调用系统调用 exit(0) 或 _exit(0) 终止进程。

if(ngx_quit){ngx_quit=0;ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"gracefully shutting down");ngx_setproctitle("worker process is shutting down");if(!ngx_exiting){ngx_exiting=1;ngx_set_shutdown_timer(cycle);ngx_close_listening_sockets(cycle);ngx_close_idle_connections(cycle);ngx_event_process_posted(cycle,&ngx_posted_events);}}
Nginx 优雅关闭机制的启动触发器。 当 Worker 进程收到 SIGQUIT 信号后, 该段逻辑会执行一次性的状态切换和资源清理动作, 将进程从“正常服务”状态切换为“待退出”状态。
#1 第一层条件:if (ngx_quit) ngx_quit:全局标志变量,初始值为 0。 置位时机: 当 Worker 进程接收到 SIGQUIT 信号时,信号处理函数 ngx_signal_handler() 将其置为 1。 检查时机: 在完成本轮 I/O 事件和定时器处理后,且在 ngx_terminate 检查和 ngx_reopen 检查之间。 注意:该标志仅用于触发优雅关闭的启动动作,执行一次后立即被清零, 因此该 if 块在整个进程生命周期中最多执行一次。
#2 ngx_quit = 0; 作用:立即将 ngx_quit 标志清零。 逻辑:防止后续循环迭代重复进入该 if 块,确保优雅关闭的初始化动作只执行一次。 意义:这是一种常见的“一次性触发”模式,将异步信号转化为一次同步的状态转换。
#3 日志与进程标题更新 日志记录: 向错误日志写入 [notice] 级别的 "gracefully shutting down", 明确记录 Worker 进程开始优雅关闭流程。 进程标题: 调用 ngx_setproctitle 修改进程名称为 "worker process is shutting down"。 运维人员通过 ps aux | grep nginx 可直观看到哪些 Worker 正在关闭中,提升可观测性。 意义:为运维提供了明确的状态可视化,便于监控和问题追踪。
#4 if (!ngx_exiting) ngx_exiting: 全局标志,表示进程已经进入待退出状态(即优雅关闭流程已启动)。 检查目的: 确保接下来的清理动作只执行一次。 由于 ngx_quit 被清零,ngx_exiting 成为防止重复执行的第二道保险。
#5 ngx_exiting = 1; 作用:将 ngx_exiting 标志置为 1,正式宣告进程进入“待退出状态”。 联动效果:从下一轮循环开始,位于循环头部的 if (ngx_exiting) 检查将每轮执行, 持续判断定时器树是否为空,直至最终退出。 意义:这是优雅关闭流程中的状态切换枢纽, 将一次性启动动作与持续性的退出条件检查分离开来。
#6 ngx_set_shutdown_timer(cycle); 作用:设置一个全局保底定时器。 逻辑:该函数通常为空操作,但某些模块(如 ngx_event_core_module)可能会设置一个超时时间 如果 Worker 在指定时间内未能自然退出(例如某些连接异常僵死),该定时器超时后会强制终止进程。 意义:防止因某些异常连接或 Bug 导致 Worker 永远无法退出,确保优雅关闭流程终将结束。
#7 ngx_close_listening_sockets(cycle); 作用:关闭当前 Worker 进程所有的监听套接字。 逻辑: 遍历 cycle->listening 数组, 对每个监听套接字调用 close() 系统调用,并从事件模块(如 epoll)中移除相关事件。 后果: 该 Worker 从此不再接受任何新的客户端连接请求。 意义: 这是优雅关闭的核心隔离动作。它切断了新请求的入口, 使 Worker 进入“只出不进”的静默状态,将资源专注于处理现有连接。
#8 ngx_close_idle_connections(cycle); 作用: 遍历连接池,主动关闭当前空闲的 Keep-Alive 连接。 空闲连接定义: 指那些已经完成了一次请求-响应交互、正等待下一次请求的 Keep-Alive 连接 逻辑: 对这些连接调用 ngx_close_connection(),立即释放资源。 不关闭活跃连接: 正在处理请求(有读/写事件挂起)的连接不会被关闭,它们将继续由事件循环处理直至完成。
#9 ngx_event_process_posted(cycle, &ngx_posted_events); 作用: 立即处理 ngx_posted_events 延迟事件队列。 背景: 在 ngx_process_events_and_timers 中, 一些优先级较低的事件会被放入 ngx_posted_events 队列, 通常在当前循环末尾统一处理。 此时主动调用该函数, 是为了在开始等待退出之前,尽快处理掉这些积压事件,推动连接状态向前演变。 意义:加速现有请求的处理进程,使 Worker 能更快地满足最终退出条件。
完整流程串联: 从 SIGQUIT 到最终退出 信号到达 → ngx_quit = 1(异步信号处理函数设置)。 主循环检测 → 进入 if (ngx_quit) 块,执行上述初始化动作: 清零 ngx_quit,更新日志和进程标题。 设置 ngx_exiting = 1,启动保底定时器。 关闭监听端口,关闭空闲连接。 立即处理延迟事件队列。 状态转换完成 → Worker 进入“待退出状态”。 后续循环 → 循环头部的 if (ngx_exiting) 检查每轮执行,等待定时器树清空。 最终退出 → 定时器树为空时,执行 ngx_worker_process_exit。

if(ngx_reopen){ngx_reopen=0;ngx_log_error(NGX_LOG_NOTICE,cycle->log,0,"reopening logs");ngx_reopen_files(cycle,-1);}}}
#1 if (ngx_reopen) ngx_reopen:全局标志变量,初始值为 0。 置位时机: 当 Worker 进程接收到 SIGUSR1 信号时,信号处理函数 ngx_signal_handler() 会将其置为 1。 检查时机:在每次事件循环末尾,处理完 ngx_quit 逻辑之后。
#2 ngx_reopen = 0; 作用: 立即将 ngx_reopen 标志清零。 逻辑: 防止在下一次循环迭代时重复执行日志重开操作,确保一次信号只触发一次实际的 reopen 动作。
#3 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); 作用: 向错误日志文件写入一条 [notice] 级别的日志,内容为 "reopening logs"。 注意: 此时写入日志使用的是旧的文件描述符,因为重新打开的动作尚未执行。 该日志会出现在日志切割前的旧日志文件中,方便运维人员追踪操作时间线。 意义: 为运维操作留下审计记录,确认信号已被 Worker 进程接收并处理。
#4 ngx_reopen_files(cycle, -1); 函数原型: void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uint_t reopen_type); 参数说明: cycle: 全局核心结构体,包含所有需要重新打开的文件信息。 -1: 特殊标志值,表示 只重新打开日志文件,不重新打开监听套接字。 若传入正值,则表示在平滑升级场景中重新打开监听端口。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 19:34:01

告别命令行!用Streamlit 5分钟为你的ROS机器人做个实时数据仪表盘

告别命令行!用Streamlit 5分钟为你的ROS机器人做个实时数据仪表盘 在机器人开发中,数据可视化往往是项目展示和调试的关键环节。想象一下,当你花费数周时间终于让机器人能够稳定行走后,如何向团队成员或投资人直观展示它的实时状态…

作者头像 李华
网站建设 2026/5/3 22:36:39

VR星际行走平台|沉浸式科普教育与未来体验的新入口

在科技高速发展的今天,虚拟现实技术已经逐渐从“酷炫娱乐”走向“深度教育”,成为现代科普与展示类场馆必不可少的互动载体。在众多VR设备中,VR星际行走平台凭借其突破传统的原地万向行走技术和高度沉浸式体验方式,正成为科普教育…

作者头像 李华
网站建设 2026/4/14 19:30:43

5分钟搞定智慧树自动刷课:免费插件让学习效率提升150%

5分钟搞定智慧树自动刷课:免费插件让学习效率提升150% 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 还在为智慧树平台繁琐的视频学习而烦恼吗&#xff1f…

作者头像 李华
网站建设 2026/4/14 19:29:41

IEEE 802.3协议全解析:从10Base-T到万兆以太网的演进之路

IEEE 802.3协议全解析:从10Base-T到万兆以太网的演进之路 以太网技术作为现代网络通信的基石,其发展历程堪称一部技术创新的编年史。从最初实验室里的简单构想,到今天支撑全球互联网的基础架构,IEEE 802.3协议家族的每一次迭代都标…

作者头像 李华
网站建设 2026/4/14 19:29:16

SP4521锂电池充放电 SOC

概述 SP4521 是一款集成开关充电和同步升压功能的单芯片解决方案,内部集成了同步开关充电模块、同步升压放电管理模块、电量检测与 LED 指示模块、保护模块。 SP4521 内置充电与放电功率 MOS,充电电流为 1A,同步升压输出电流为 1A。 SP4521 采用专利的充…

作者头像 李华
网站建设 2026/4/14 19:29:15

python qrcode

# 聊聊Python里的二维码生成 二维码这东西现在随处可见,付款、加好友、下载App,扫一下就行。但你知道怎么用Python自己生成二维码吗?今天就来聊聊qrcode这个库。 他是什么 qrcode是Python里一个专门用来生成二维码的库。说白点,它…

作者头像 李华