官方文档参考:http://nginx.org/en/docs/control.html#upgrade
这里所说的热部署指的是需要升级nginx二进制文件,而不是简单的更新配置,如果只是更新配置,直接使用nginx -s reload即可。看到网上有的文章关于增加新模块热部署也使用nginx -s reload 这是不对的,这只能重新加载配置文件,但并不会使用新的nginx可执行文件。
nginx 安装参考 https://blog.csdn.net/wwxuelei/article/details/88114241
nginx 允许我们通过向她发送信号来控制nginx。nginx的主进程号一般写在 /usr/local/nginx/logs/nginx.pid(即nginx运行时的日志目录下的nginx.pid)。nginx主进程支持以下信号:
TERM, INT | fast shutdown (快速停止,相当于nginx -s stop ) |
QUIT | graceful shutdown (优雅的停止,处理完已经接受的请求, 相当于nginx -s quit) |
HUP | changing configuration, keeping up with a changed time zone (only for FreeBSD and Linux), starting new worker processes with a new configuration, graceful shutdown of old worker processes 更改配置,以新的配置文件开启新的worker进程,并优雅的关闭老的worker进程,相当于 nginx -s reload |
USR1 | re-opening log files (重新打开日志文件, 相当于nginx -s reopen ) |
USR2 | upgrading an executable file (升级可执行文件) |
WINCH | graceful shutdown of worker processes (优雅地关闭worker进程) |
单个的worker进程也可以直接通过信号来控制(虽然一般不需要),支持的信号为
TERM, INT | fast shutdown (快速停止) |
QUIT | graceful shutdown (优雅停止) |
USR1 | re-opening log files (重新打开日志文件,这里有些疑问,会影响主进程和其它进程吗?) |
WINCH | abnormal termination for debugging (requires debug_points to be enabled) |
前提:这些操作的前提是nginx启动时不是使用环境变量启动的(比如,设置了环境变量PATH,然后直接nginx启动)。具体原因看第三步。
1. 备份原执行文件nginx 为 nginx.old ,以便必要时回滚
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
2. 将新编译好的nginx执行文件拷过来
cp ~/nginx-1.14.2/objs/nginx /usr/local/nginx/sbin/
3. 向nginx主进程发送USR2 信号,通知nginx要对它进行升级
kill -USR2 37786 #37786是旧的主进程号
执行此命令后,主进程首先将logs/nginx.pid重命名为nginx.pid.oldbin。然后运行新的可执行文件(启动新的主进程),新的 主进程将开启新的worker进程。其中新的主进程的父进程是旧的主进程。
注意:如果你的nginx启动时是过环境变量来启动(直接nginx), 执行完上面的命令后,会发现并没有开启新的进程。查看logs/error.log,可以如下错误信息
execve() failed while executing new binary process “nginx” (2: No such file or directory)
这是因为在这个命令执行过程中是识别不到设置的环境变量,所以找不到指定的新的可执行文件。从上面的图中也可以看出,新的主进程显示为 nginx:master process sbin/nginx,是与老进程采用相同的命令方式。
解决方法:
1)启动nginx时应使用绝对路径:如/usr/local/nginx/sbin/nginx。
2)如果像上面的截图一样,使用的是相对路径sbin/nginx, 则执行kill -USR2时,也应在相同的目录。
4. 之后所有的workder进程继续接收请求。我们接下来再发送WINCH 信号到旧的主进程,它会通知旧的worker进程优雅的关闭,然后退出。
注意:这里旧的主进程并不会退出。如果需要它还可以重新拉取旧的worker进程。这主要是为了防止新的nginx有问题时回滚。如果需要回滚,可以有以下两种方式(注意:如果已经更新过配置文件,需要先回滚配置文件):
1) 发送 HUP 信号给旧的主进程。它会重新加载配置并重新拉起worker进程,然后发送QUIT信号给新的主进程,优雅的关闭所有新的进程。这样就回到升级前的情况。如果就此停止的话,记得恢复原来的nginx执行文件。
2) 直接向新的主进程发送 TERM 信号,直接关闭所有的新进程。如果因为某种原因新的worker进程未正常既出的话,可以直接kill掉。当新的主进程退出后,旧的主进程会自己拉起worker进程,并且会将logs/nginx.pid.oldbin 恢复成logs/nginx.pid。
5. 如果一切顺利,发送QUIT信号给旧的主进程,只留下新的进程。
6. 更新配置文件,并重新加载配置文件
鉴于升级nginx时,可能需要1到n个相关的配置文件,如果在升级时出现问题,需要回滚操作比较麻烦,所以如果可行,建议先只升级nginx可执行文件,升级成功后,再更新相关配置文件,然后nginx -s reload重新加载配置文件。
实现nginx热部署的前提:nginx是路径方式启动的
执行步骤:
1. mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old #备份原nginx执行文件
2. cp [新的nginx文件] /usr/local/nginx/sbin #拷贝新的执行文件
3. kill -USR2 [旧的主进程id] #通知旧的主进程将要进行升级
4. kill -WINCH [旧的主进程id] #通知旧的主进程优雅地关闭它的worker 进程
5. kill -QUIT [旧的主进程id] #通知旧的主进程优雅的退出
6. 更新配置文件,并重新加载