nginx实现热升级的原理
nginx 启停操作
sudo ./nginx -c /usr/local/src/nginx/conf/nginx.conf //启动
sudo /usr/local/src/nginx/sbin/nginx -s reload //平滑重启
./nginx -s stop #立即停止服务
./nginx -s quit #优雅的停止服务
./nginx -s reload #重载配置文件
./nginx -s reopen #重新开始记录日志文件
停止:
ps -ef|grep nginx
kill -QUIT 2072 //停止
kill -TERM 2132
kill -9 nginx //强制停止
重启:
kill -HUP 进程号热升级简介
热升级大致分为两步
编译好Nginx的二进制文件
通过信号,完成新老进程的平滑过渡,保证升级期间服务可用。
热升级步骤
第一步:先查看原先编译的参数。-V可以查看编译时的参数(-v时查看版本)。在新编译时,要将原有的模块参数也加上,否则原有的模块不会编译进去。
第二步:开始编译,编译过程和上篇一致,增加了要添加模块的参数。
通过 -–add-module可以编译第三方的模块到Nginx。 这里只需要make编译,不要make install安装。
老版的用 --add-module,新版的用 --add-dynamic-module
编译完成后的nginx二进制文件在objs目录。
第三步:备份和替换
第四步:热升级。至此我们只是替换了二进制文件,但是现在服务中的Nginx进程还是由原来的nginx二进制文件启动的,所以请求还是走原有的逻辑。
此时所有的请求都会平滑过渡到新的worker进程。但是旧的master进程13195还在,只是没有worker进程,如果要回退,只需要拉回旧的nginx拉回worker进程。如果运行一段时间没有问题,可以通过kill -QUIT 13159彻底关闭老进程
回滚
将原来备份好旧版本的二进制文件的再复制回去
热升级流程
1. 将旧Nginx文件换成新的Nginx文件(注意备份)
2. 像master进程发送USER2信号会执行下面的动作:
master进程修改/logs/nginx.pid文件名(该文件是用来记录启动Nginx后的master进程号),给其加后缀.obin。因为新起的进程会生成一个nginx.pid文件,所以会修改原有文件的名称。这样做可以在回滚时找到对应的进程号。
master进程用新Nginx文件启动新的master进程
发送WINCH信号,关闭原有旧worker进程
向老进程发送QUIT信号,关闭老master,这时候进程退出(3,4步也可以合成4一步,这样在关闭老master进程时,老master进程会通知自己的worker进程关闭)
如果需要回滚:向老master发送HUP,向新master发送QUIT

信号

其中发送信号的方式有两种
通过 kill -HUP 12392这种方式直接向进程发送信号。
通过nginx命令行方式:nginx -s reload
第二种实际上就是利用logs目录下的nginx.pid读取进程id然后发送对于的信号,本质一样。
上面红色标识的信号只能通过kill -命令直接发送给对应进程。而没有对应的nginx命令。
reload流程(热重启)
向master进程发送HUP信号(等同reload命令)
master进程校验配置语法是否正确
master进程打开新的监听端口,
master进程用新配置启动新的worker子进程
master进程向老worker子进程发送QUIT信号
老worker进程关闭监听句柄,处理完当前连接后结束进程
说明:
在新的配置文件里,如果我们监听了新的端口,master会打开这个监听端口,以便新起的worker进程进行监听和任务处理
老worker进程正常情况下,在处理已连接的请求后,会优雅退出,有时会出现老worker进程长时间存在,但是也只是影响已经建立的连接。
监听句柄
即调用过listen的socket。
子进程会自动共享父进程被listen的socket。句柄可以理解就是 socket,或者叫fd文件句柄。
集群问题
如果是频繁修改upstream集群信息,那么不建议使用reload方式,你的修改目标非常简单明确,而reload是重新对所有配置生效,建议使用openresty实现API服务,由API来直接修改upstream信息。
端口问题
新配置中关闭的端口,reload之后也不会关闭,因为master进程不会关闭端口。
SIGHUP
把cycle对象传递给ngx_init_cycle(),创建一个新的cycle对象,完全复制老cycle,但更新了配置文件,随用ngx_cycle全局指针切换到新的cycle对象,完全reload。
最后更新于
这有帮助吗?