分析典型案例:
之所以挑这两个,不仅仅是应用广泛,而且两个的进程模型比较类似,都是Master、Worker的形式,在热重启上思路和做法又基本不同,比较有参考意义 知识点:
这几个知识点不难,区别只在于Celery和Gunicorn的应用方式。如果脑海中有这样的知识点,这篇文章也就是开阔下视野而已。。。 Celery和Gunicorn都会在接收到HUP信号时,进行热重启操作 Celery的重启:关旧Worker,然后execv重新启动整个进程 Gunicorn的重启:建立新Worker,再关旧Worker,Master不动 下面具体的看下它们的操作和核心代码。 对于Celery: def _reload_current_worker():
platforms.close_open_fds([
sys.__stdin__, sys.__stdout__, sys.__stderr__,
])
os.EⅩEcv(sys.EⅩEcutable, [sys.EⅩEcutable] sys.argv)
def install_worker_restart_handler(worker, sig='SIGHUP'):
def restart_worker_sig_handler(*args):
"""Signal handler restarting the current python program."""
import atexit
atexit.register(_reload_current_worker) from celery.worker import state
state.should_stop = EX_OK
platforms.signals[sig] = restart_worker_sig_handler
HUP上挂的restart_worker_sig_handler 就做了两件事:
考虑到这个执行顺序,应该就能明白Celery 是Master和Worker都退出了,崭新呈现。。 看过APUE的小伙伴,应该比较熟悉 atexit 了,这里也不多说。os.EⅩEcv还挺有意思,根据Python文档,这个函数会执行一个新的函数用于替换掉当前进程,在Unix里,新的进程直接把可执行程序读进进程,保留同样的PID。 在Python os标准库中,这是一整套基本一毛一样的函数,也许应该叫做函数族了:
以exec开头,后缀中的l和v两种,代表命令行参数是否是变长的(前者不可变),p代表是否使用PATH定位程序文件,e自然就是在新进程中是否使用ENV环境变量了 然后给worker的state.should_stop变量设置成False。。。模块共享变量这个是Python FAQ里提到的一种方便的跨模块消息传递的方式,运用了Python module的单例。我们都知道Python只有一个进程,所以单例的变量到处共享 而should_stop这个变量也是简单粗暴,worker在执行任务的循环中判断这个变量,即执行异步任务- |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|