python热部署,模拟nginx热部署

热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用。

首先在本地模拟一个线上需要升级 Nginx 的环境,假设旧版本为 nginx-1.0.15,需要升级到 nginx-1.16.0。

配置旧版本

# 下载 nginx-1.0.15

wget http://nginx.org/download/nginx-1.0.15.tar.gz

# 解压压缩包

tar -zxf nginx-1.0.15.tar.gz

# 进入解压后的目录

cd nginx-1.0.15

# 配置 nginx

./configure --prefix=/home/nginx

# 编译安装

make && make install

# 运行 nginx

sudo /home/nginx/sbin/nginx

此时访问服务器地址应该可以看到 nginx 的欢迎页面了。

获得新版本二进制

# 下载 nginx-1.16.0

wget http://nginx.org/download/nginx-1.16.0.tar.gz

# 解压压缩包

tar -zxf nginx-1.16.0

# 进入解压后的目录

cd nginx-1.16.0/

# 配置 nginx

./configure --prefix=/home/nginx

# 只编译不需要安装

make

在编译后的 objs 目录中,可以看到二进制文件 nginx。

热部署

经过以上步骤,我们实现了一个正在运行的旧版本 nginx 和编译完成的新版本 nginx 二进制执行文件。

热部署的流程是:

备份旧的 nginx 可执行文件

新的 nginx 可执行文件直接替换旧的(此时旧的 nginx 进程还在运行)

向 nginx master 进程发送热部署信号,新的 nginx 进程启动,旧的 worker 不再就收请求。

关闭旧的 worker 进程,完成热部署。

# 备份

cp /home/nginx/sbin/nginx /home/nginx/sbin/nginx.old

# 替换

cp -f objs/nginx /home/nginx/sbin/nginx

# 查看 master pid

ps -ef | grep nginx

root 23712 1 0 21:21 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx

nobody 23715 23712 0 21:21 ? 00:00:00 nginx: worker process

# 发送热部署信号,这里 master pid 替换为自己查询到的

kill -USR2 23712

# 查看当前 nginx 进程情况,27522 就是新的 master 进程

ps -ef | grep nginx

root 23712 1 0 21:21 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx

nobody 23715 23712 0 21:21 ? 00:00:00 nginx: worker process

root 27522 23712 0 21:41 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx

nobody 27524 27522 0 21:41 ? 00:00:00 nginx: worker process

# 关闭旧的 worker

kill -WINCH 23712

# 再次查看进程,可以发现旧的worker进程关闭了

ps -ef | grep nginx

root 23712 1 0 21:21 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx

root 27522 23712 0 21:41 ? 00:00:00 nginx: master process /home/nginx/sbin/nginx

nobody 27524 27522 0 21:41 ? 00:00:00 nginx: worker process

保留旧的 master 进程是为了在新的版本存在问题时,可以快速回退到原版本。如果发现问题要紧急回滚呢?

cp -f nginx.old nginx

# 拉起旧版本的worker进程(-HUP 相当于 -s reload)

kill -HUP old_master_pid

# 让新版本的 worker 不再接受请求

kill -USR2 new_master_pid

# 关闭新版本的 woker 进程

kill -WINCH new_master_pid

如果确认无误要退出老版本的 nginx,可以执行命令:

kill -QUIT old_master_pid