nginx之热部署,在线升级 

官方文档参考:http://nginx.org/en/docs/control.html#upgrade

前言

      这里所说的热部署指的是需要升级nginx二进制文件,而不是简单的更新配置,如果只是更新配置,直接使用nginx -s reload即可。看到网上有的文章关于增加新模块热部署也使用nginx -s reload 这是不对的,这只能重新加载配置文件,但并不会使用新的nginx可执行文件。

      nginx 安装参考 

基础知识点

       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热部署操作步骤及执行过程说明

       前提:这些操作的前提是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配置热更新_配置文件

         注意:如果你的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进程优雅的关闭,然后退出。 

Nginx热更新流程 nginx配置热更新_配置文件_02

注意:如果已经更新过配置文件,需要先回滚配置文件):

     1) 发送 HUP 信号给旧的主进程。它会重新加载配置并重新拉起worker进程,然后发送QUIT信号给新的主进程,优雅的关闭所有新的进程。这样就回到升级前的情况。如果就此停止的话,记得恢复原来的nginx执行文件。

Nginx热更新流程 nginx配置热更新_热部署_03

    2) 直接向新的主进程发送 TERM 信号,直接关闭所有的新进程。如果因为某种原因新的worker进程未正常既出的话,可以直接kill掉。当新的主进程退出后,旧的主进程会自己拉起worker进程,并且会将logs/nginx.pid.oldbin 恢复成logs/nginx.pid。

    

   5. 如果一切顺利,发送QUIT信号给旧的主进程,只留下新的进程。

Nginx热更新流程 nginx配置热更新_Nginx热更新流程_04

   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. 更新配置文件,并重新加载