说明:以master为例
根据uwsgi文档,当uwsgi接收到SIGHUP信号的时候,会优雅地重载所有的worker和master进程。(参考:uwsgi中文)
而在master_loop()
方法(位于core/master.c
)中,注册了接收到SIGHUP信号的处理方法为grace_them_all
:uwsgi_unix_signal(SIGHUP, grace_them_all);
起始:void grace_them_all(int signum)
位于uwsgi/core/uwsgi.c中
在这个方法中,uwsgi会针对不同的模式,修改状态,关闭清理不同的进程。具体执行如下: 1. 检查uwsgi实例是否已经在重载,或者正在关闭。是则直接返回,以避免再次重载。 2. lazy模式下,对所有正在运行中的worker,调用uwsgi_curse(i, SIGHUP)
,然后直接返回 3. 设置uwsgi的状态为正在优雅重载(uwsgi.status.gracefully_reloading = 1;
) 4. 调用uwsgi_destroy_processes()
1. 给spooler发送SIGKILL
信号杀死spooler 2. 停止uwsgi的守护进程(daemon)们 3. 杀死gateway(来自uwsgi.h中的注释:gateway是由master管理的进程,用以扩展服务器的核心特性,它可以prefork或者spawn线程) 4. 杀死emperor 5. 如果定义了UWSGI_SSL
,还要调用uwsgi_legion_announce_death()
宣告legion的death状态 6. 如果设置了即使在重载时也要强制取消订阅请求(unsubscribe_on_graceful_reload
),那么则取消订阅(调用uwsgi_unsubscribe_all()
) 7. 对于每个worker,如果不是master的话,则调用uwsgi_curse(i, SIGHUP);
来杀死worker 8. 对于每个mule,如果不是父mule的话,则调用uwsgi_curse_mule(i, SIGHUP);
来杀死Mule
整个过程图如下:
给指定worker id的worker发送死亡信号sig:uwsgi_curse
位于uwsgi/core/master_utils.c中
1 | void uwsgi_curse(int wid, int sig) { |
管理worker的优雅重载:void gracefully_kill(int signum)
位于uwsgi/core/uwsgi.c中
master通过kill()
函数来向worker发送SIGHUP信号。 而在uwsgi_worker_run()
方法中注册了信号SIGHUP
的处理方法为gracefully_kill
:uwsgi_unix_signal(SIGHUP, gracefully_kill);
。我们来看看这个方法又进行了什么操作: 1. 将worker管理的下一个请求(manage_next_request
)置为0(表示的意思要再研究下) 2. 对于多线程,等待线程终止(wait_for_threads()
),等待请求处理完成之后,在需要的时候(worker.close_sockets不为0)关闭所有的socket,最后调用exit(UWSGI_RELOAD_CODE)
退出。结束该方法。 3. 对于异步模式,目前没有什么好的方式进行优雅重载,因此处理方式则是,在需要的时候(worker.close_sockets不为0)关闭所有的socket,然后调用exit(UWSGI_RELOAD_CODE)
退出。结束该方法。 4. 对于无待处理请求的worker,在需要的时候(worker.close_sockets不为0)关闭所有的socket,然后调用exit(UWSGI_RELOAD_CODE)
退出
这里的
exit()
函数并非系统的exit
,而是一个宏定义:#define exit(x) uwsgi_exit(x)
图解如下:
退出:void uwsgi_exit(int status)
- 将uwsgi的
last_exit_code
属性值为status值 - 调用系统函数
exit
退出当前进程
通过上面一系列操作,uwsgi就完成了重载中的stop
一步。接下来就是start
了。这个阶段,我们稍后再说~~