在Django+Gunicorn+Nginx环境下,如何更优重载Gunicorn?
解决Gunicorn在config.ini变更后的平滑重载问题
先给你明确几个关键点:Gunicorn自带的--reload选项默认只盯着Python文件(.py)的变化,config.ini这种非Python配置文件它根本不会监测,而且这个选项本来就是给开发环境用的,生产环境开着会有性能损耗,完全不适合你的场景。
生产环境下最优的做法是给Gunicorn主进程发SIGHUP信号,这会触发它启动新的worker进程加载更新后的配置,旧worker会把手里的请求处理完再优雅退出,全程不会断服务,比硬重启友好太多。
结合你的SaltStack部署流程,给你两种实用的实现方案:
方案1:用systemd管理Gunicorn(首推)
如果你的Gunicorn是用systemd服务跑的,先确认你的gunicorn.service配置里有重载信号的定义(一般默认就配置好了):
[Service] User=www-data Group=www-data ExecStart=/usr/bin/gunicorn --workers 3 --bind unix:/var/run/gunicorn.sock myproject.wsgi:application ReloadSignal=HUP
然后在SaltStack的state文件里,给config.ini的文件管理规则加上onchanges触发,调用systemd的重载命令:
/etc/myproject/config.ini: file.managed: - source: salt://myproject/config.ini.jinja - template: jinja - user: www-data - group: www-data - mode: 644 - onchanges: - cmd: reload_gunicorn reload_gunicorn: cmd.run: - name: systemctl reload gunicorn - onlyif: systemctl is-active --quiet gunicorn
方案2:通过PID文件发送信号
要是没用到systemd,而是用PID文件记录Gunicorn主进程ID,直接发HUP信号就行:
/etc/myproject/config.ini: file.managed: - source: salt://myproject/config.ini.jinja - template: jinja - user: www-data - group: www-data - mode: 644 - onchanges: - cmd: reload_gunicorn reload_gunicorn: cmd.run: - name: kill -HUP $(cat /var/run/gunicorn.pid) - onlyif: test -f /var/run/gunicorn.pid
额外注意事项
- 生产环境务必关掉
--reload,别给自己的服务加没必要的负担; - 要确保Django视图不是只在启动时读一次
config.ini,最好每次需要时重新读取,或者做个配置缓存+失效机制,不然就算Gunicorn重载了,旧worker可能还在拿缓存的旧配置干活; - 测试的时候,改完
config.ini跑一遍SaltStack状态,然后检查Gunicorn的worker进程是不是更新了,同时验证服务能不能正常响应请求。
内容的提问来源于stack exchange,提问作者Dalek Sec
相关产品推荐
相关产品推荐

