Nginx配置文件重载原理与热部署实战
Nginx配置文件重载原理与热部署实战
Nginx作为常用的Web服务器和反向代理软件,在实际运维中经常会遇到配置文件重载和程序升级的需求。本文详细介绍了Nginx配置文件重载的原理和具体步骤,以及如何实现Nginx的热部署,包括升级和回滚的具体操作,对于Nginx运维人员和开发人员具有较高的参考价值。
配置文件的重载原理
我们可以通过给Nginx的master进程发送 HUP 信号, 或者是使用Nginx的二进制程序 执行 reload命令来重新载入配置文件, 从而实现Nginx的一个平滑升级。那么,Nginx的背后到底是发生了一个什么样的事情去保证新老配置的平滑过渡的呢?
reload 重载配置文件的流程
第一步肯定是向 master 进程发送 HUP 信号 或者 reload命令, 我们可以直接给 master 进程的PID发送
kill -s SIGHUP 12345
这样一个信号, 或者使用
nginx -s reload
第二步,master进程会检查整个配置文件( 包含内部 include 的配置文件) 依次检查相关语法是不是正确,它才会去执行下一步
第三步,master进程可能会打开新的监听端口。
第四步,master进程使用新的配置文件启动新的worker子进程,这时候新老进程可能并存
第五步,master进程向老的worker子进程发送 QUIT 信号
第六步,旧的worker进程关闭监听句柄,处理完当前连接后关闭进程
Nginx的热部署
Nginx 通常是运行于整个业务系统的一个边缘节点,通常是最先接收来自远端的用户的请求的。那对于这样一个应用来说的话,如何对它进行一个热升级是非常重要的。所谓热部署,就是说我们可以在中断现有业务的情况下,平滑的将新开发的应用程序版本给升级上去。
热部署的升级流程
- 将旧的Nginx文件替换成新的nginx文件
- 这里的nginx文件是nginx主程序文件, 例如:sbin/nginx
- 对 conf 目录结构等保持不变
- 向master进程发送USR2信号
- 促使 master 进程修改 pid 文件,加后缀 .oldbin
- 通常,在 logs/nginx.pid => logs/nginx.pid.oldbin
- 这样后面master进程会用新的nginx文件启动新的master进程
- 这时候旧的master进程和新的master进程会同时存在
- 验证新上线的Nginx程序是否满足预期,如果满足新预期,则
- 向旧的master进程发送WINCH信号, 旧的worker子进程退出
- QUIT 信号会让 master 和 worker 子进程一起退出
- WINCH信号只会让 worker 子进程退出,避免接收用户请求
- 使用WINCH 是为回滚情形做准备:
- 向旧master发送HUP,向新master发送QUIT
- 旧的worker子进程会被重启,新的master进程及其子进程会停止
实际演示升级Nginx程序
假设主目录是 /opt/nginx 下
$ ll
注意,新版本的nginx的目录结构需要与旧版一致
可以通过
$ /opt/nginx/sbin/nginx -V
不仅可以查看版本,而且可以查看编译安装时的参数
要确保目录下的一些参与编译的东西一致
升级步骤
- 备份 nginx 二进制程序
$ cp nginx nginx.bak
- 之后将新编译好的 nginx 二进制文件对其进行替换
- 之后,给旧的nginx进程发送信号
$ kill -s SIGUSR2 27454
- 查看现在的情况
可以看到新旧主/子进程并存$ ps -ef | grep nginx
- 可以进入 logs 目录,看到有了 nginx.pid.oldbin 的生成
可以看到是之前的主进程 27454$ cat /logs/nginx.pid.oldbin
可以看到是新的主进程 27457$ cat /logs/nginx.pid
- 至此,新老 nginx 并存
- 现在给旧的master进程发送信号,关闭子进程
$ kill -s SIGWINCH 27454
- 再次查看
旧的master进程子进程已经没有了$ ps -ef | grep nginx
- 目前只有旧的主进程和新的主/子进程了
- 现在可以对 新的 master 主进程做测试,来验证是否符合预期
- 符合预期后,退出旧的主进程
$ kill -s SIGQUIT 27454
- 至此,旧的主/子进程全部退出,取而代之的是新的主/子进程
- 去 logs日志中查看,nginx.pid.oldbin 也随着被删除
回滚步骤
发现新版 nginx 不适合,需要回滚,回到之前旧的进程只剩master进程时
- 给旧的主进程发送信号:
让旧的master进程重新拉起旧的worker子进程$ kill -s SIGHUP 27454
- 将新的master进程退出
$ kill -s SIGQUIT 27457
- 验证:
发现已实现回滚$ ps -ef | grep nginx
本文原文来自CSDN,作者Tyro_java