uwsgi graceful reload

0 评论
/ /
0 阅读
/
1983 字
17 2022-03

传统重启弊端:


后台上线功能,以往的做法是当有对代码进行更改,需要将新代码提供给用户时,将uwsgi服务器重新启动以使更改生效,但这个重启过程会将所有uwsgi的worker进程强行kill掉,然后再重新启动这些worker,导致的结果:

worker正在处理的请求无法正常处理完,
重启过程中uwsgi无法正常接收请求,请求报502的错误,特别是由于某些原因重启时间可能很久
从stop uwsgi到start uwsgi需要一定时间,这期间就损害了用户的体验:

在网站上看到服务不可用的错误
在请求处理中用户等待很久
服务重启遇到程序bug,导致重启失败


优雅重启过程:


优雅的重启是一门艺术,优雅重启的方式有多种,但经过测试,链式重启是最优选择之一,且实现起来非常方便

链式重启的实现过程是一个接一个工人依次重新加载启动,直到所有工人都重新加载完毕。比如你有五个工人,工人A,工人B,工人C...,当你触发链式重启时:

若工人A此刻正在处理请求,链式重启允许它完成此次请求,工人A开始重新加载最新代码
如果工人A顺利完成加载,此时工人A接收到的请求都由最新代码处理,而其他4个工人则依然运行旧代码
工人A顺利完成加载后,依次由工人B开始重新加载最新代码,重复此操作,直到每个工人都获取新代码。链式重启过程完成
如果前一个工人没有加载成功,那么后一个工人也不会进行重启加载,这就意味着,如果程序有bug,其他工人都不会受到任何影响,依然能正常接收请求,这点非常棒,与传统野蛮重启方式相比有明显优势


优雅重启实现:


链式重启的实现非常简单,是通过touch一个文件来触发优雅重启过程:

打开uwsgi的以.ini后缀的配置文件,添加这一行:

lazy-apps = true


这里的lazy-apps是uwsgi的其中一种加载模式,不指定的话,默认情况下,uwsgi在第一个进程中加载整个应用程序,在加载应用程序之后,它会多次fork本身,这种方式虽然能减少应用程序的内存使用,但它是对整个堆栈进行了重新加载,比较野蛮,而不是单独对每一个工人重新加载。而lazy-apps模式会为每个工人加载应用程序一次。假设它的工人数是n,那么它的时间复杂度就是O(n),这样可能会消耗更多的内存,但这种确保了服务一直处于可用状态,不至于停机,这也是我们第二部分重启过程的思路,每个工人都重新加载,而默认的模式做不到这一点,所以想要做到优雅重启,需要将uwsgi默认设置为lazy-apps

指定touch-reload-chain的文件

touch-chain-reload = /home/ymserver/demeter/master/backend/website/demeter/settings.py


这个指定一个链式重启的touch文件,每次touch这个文件来触发优雅重启过程,无论何时更新代码,只需touch settings.py即可。如果跟踪uwsgi日志,您可以看到uwsgi如何执行此过程。以下是我实操的截图,我这里有8个工人在跑,

总结:

优点:
    保证上线过程服务高可用,提升用户体验
    若新代码油污导致重启失败的,不会影响其他工人运行
缺点:
    仅对代码更新有用
    占用较大内存
    需要增加一些工人来做逐个重启


原文链接:https://blog.csdn.net/asas043/article/details/102443649