如何使用Ansible无停机重载Gunicorn服务器
Gunicorn无停机重载的Ansible实现方案
针对你目前用kill -9硬杀进程导致服务停机的问题,Gunicorn本身支持通过信号机制实现无停机重载,以下是两种可行的Ansible实现方案:
方案一:HUP信号平滑重载(适用于代码/配置小更新)
Gunicorn主进程收到HUP信号后,会重新加载配置和应用代码,启动新的工作进程,同时逐步关闭旧工作进程,全程不会中断服务请求。
推荐配置PID文件的实现方式
启动Gunicorn时添加--pid /var/run/gunicorn.pid参数生成PID文件,后续进程管理更便捷:
- name: 检查Gunicorn PID文件是否存在 stat: path: /var/run/gunicorn.pid register: gunicorn_pid_file - name: 发送HUP信号重载Gunicorn主进程 ansible.builtin.shell: "kill -HUP $(cat /var/run/gunicorn.pid)" when: gunicorn_pid_file.stat.exists
无PID文件的实现方式
如果未配置PID文件,可通过进程查找定位Gunicorn主进程:
- name: 获取Gunicorn主进程ID ansible.builtin.shell: "ps aux | grep 'gunicorn.*django_my_website.wsgi' | grep -v grep | awk '{print $2}'" register: gunicorn_master_pid - name: 发送HUP信号重载Gunicorn ansible.builtin.shell: "kill -HUP {{ gunicorn_master_pid.stdout }}" when: gunicorn_master_pid.stdout != ""
方案二:USR2+WINCH信号零停机重启(适用于依赖更新、重大代码变更)
如果涉及Python依赖更新或重大代码重构,HUP信号可能无法完全加载新运行环境,此时可通过USR2+WINCH信号实现新旧进程无缝切换:
- 发送
USR2信号:旧主进程会启动一个使用新代码/依赖的新主进程 - 发送
WINCH信号:旧主进程关闭所有旧工作进程,由新进程接管请求 - 可选发送
QUIT信号:确认新进程正常后,关闭旧主进程
- name: 检查Gunicorn PID文件是否存在 stat: path: /var/run/gunicorn.pid register: gunicorn_pid_file - name: 发送USR2信号启动新Gunicorn主进程 ansible.builtin.shell: "kill -USR2 $(cat /var/run/gunicorn.pid)" when: gunicorn_pid_file.stat.exists - name: 等待新进程初始化完成(根据服务启动速度调整时间) ansible.builtin.pause: seconds: 10 - name: 发送WINCH信号让旧主进程关闭旧工作进程 ansible.builtin.shell: "kill -WINCH $(cat /var/run/gunicorn.pid)" when: gunicorn_pid_file.stat.exists # 可选:确认新进程稳定后,关闭旧主进程 - name: 发送QUIT信号关闭旧Gunicorn主进程 ansible.builtin.shell: "kill -QUIT $(cat /var/run/gunicorn.pid.oldbin)" when: gunicorn_pid_file.stat.exists
注意事项
- Gunicorn必须以主进程模式运行(默认即可,使用
--daemon后台运行也不影响) - 优先配置PID文件,避免进程查找的不确定性
- 方案二中,旧主进程会自动生成
/var/run/gunicorn.pid.oldbin文件,用于管理旧进程 - 如果使用虚拟环境,确保Ansible任务的
venv参数与Gunicorn启动环境一致
内容的提问来源于stack exchange,提问作者Minh Quang Nguyen
相关产品推荐
相关产品推荐

