#num1 1、开始之前首先查看当前的使用版本以及编译时的参数: [root@www ~]# /usr/local/nginx/sbin/nginx -V nginx version: nginx/1.12.2 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013 TLS SNI support enabled configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module 将编译参数复制出来,编译新版本的时候会用到。 2、下载新版本:http://nginx.org/en/download.html cd nginx-1.14.0 ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module make 3、执行完成之后,不需要make install ,备份原来的二进制启动文件,然后将新版的启动文件拷贝过去 mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak [root@www nginx-1.14.0]# cp objs/nginx /usr/local/nginx/sbin/nginx 4、测试一下复制过来的文件是否生效: [root@www nginx-1.14.0]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful 5、发送USR2信号给nginx master 进程(nginx服务接收到USR2信号后,首先会将旧的nginx.pid文件添加后缀.oldbin,变为nginx.pid.oldbin,然后执行新版本的二进制文件启动服务,如果新的服务启动成功,系统中将有新旧两个Nginx服务共同提供web服务) kill -USR2 `cat /usr/local/nginx/logs/nginx.pid` [root@www nginx-1.14.0]# ps -ef | grep nginx root 22644 1 0 23:30 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx www 22648 22644 0 23:30 ? 00:00:00 nginx: worker process root 25784 22644 0 23:47 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx www 25789 25784 0 23:47 ? 00:00:00 nginx: worker process 6、通过发送WINCH信号(平缓停止worker process)和QUIT信号(平缓停止Nginx服务)停止旧的Nginx服务进程 kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin` kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin` 7、升级完成,最后看一下nginx版本: /usr/local/nginx/sbin/nginx -v nginx version: nginx/1.14.0 --------- #num2 Nginx热更新相关知识 1、inotify文件系统监控特性 Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除、读、写和卸载操作等。inotify是Linux内核提供的一个文件系统变化通知机制,从2.6.13版本的内核开始提供,比如你在创建一个文件时它可以通知你哪个文件被创建了,删除文件时通知你哪个文件被删除了,修改文件时通知你哪个文件被修改了,关闭文件时哪个文件被关闭了,是可写关闭还是不可写关闭等等。 2、Nginx配置热更新 NginX采用Master/Worker的多进程模型,Master进程负责整个NginX进程的管理。主要包括:热更新、停机、日志重启等。 NginX的配置修改之后,在不影响当前服务的情况下进行更新。 信号: HUP 过程: 分为Master部分和Worker部分。 Matser进程: 1> 通过ngx_signal_hanlder解析出获取的信号,置ngx_reconfigure=1,标识Master要进行配置热更新操作。 2> 调用ngx_init_cycle初始化新的cycle(重新加载nginx.conf以及各模块的初始化)。 3> 调用ngx_start_worker_process启动新的Worker子进程,子进程标识just_respwan=1(NGX_PROCESS_JUST_RESPAWN)表示刚启动,区分新旧进程。 4> 调用ngx_start_cache_manager启动新的cache manager子进程和cache loader子进程。子进程标识just_respawn=1(NGX_PROCESS_JUST_RESPAWN)表示刚启动,区分新旧进程。 5> 睡眠100毫秒之后,调用ngx_signal_worker_process优雅的关闭老的worker、cache manager和cache loader进程。注意:只向just_respawn=0的进程进行发送信号。 Worker进程: 1> 通过ngx_signal_handler解析出为QUIT信号,置ngx_quit=1 2> 调用ngx_close_listening_sockets关闭监听端口。设置ngx_exting=1 3> 如果定时器红黑树中为空,执行ngx_worker_process_exit退出。 3. Nginx可执行程序热更新 Nginx可执行程序升级后,在不影响当前服务的情况下进行更新。 步骤1:信号:USR2 过程: Master进程: 1> 通过ngx_signal_handler解析获取信号,置ngx_change_binary=1。 2> 调用ngx_new_binary=ngx_exec_new_binary 函数启动新的binary的NginX。(期间:需要进行老的环境变量的拷贝、socket句柄的传递、pid文件的拷贝等)。 此时,系统中同时存在两个Nginx(新、老)同时提供服务。 Woker进程: 无操作 步骤2:信号:WINCH 过程: Master进程: 1> 通过ngx_signal_handler解析获取信号,置ngx_noaccept=1。 2> 置ngx_noaccepting=1,调用ngx_signal_worker_processes向子进程发送QUIT信号。即Worker进程优雅的退出。 如果此时没啥问题就可以直接关闭老的NginX Master进程了。(如果有问题,还有类似过程的回滚操作...) 3、Nginx可执行程序热更新流程步骤 步骤1、升级nginx二进制文件,需要先将新的nginx可执行文件替换原有旧的nginx文件,然后给nginx master进程发送USR2信号,告知其开始升级可执行文件;nginx master进程会将老的pid文件增加.oldbin后缀,然后拉起新的master和worker进程,并写入新的master进程的pid。 步骤2、在此之后,所有工作进程(包括旧进程和新进程)将会继续接受请求。这时候,需要发送WINCH信号给nginx master进程,master进程将会向worker进程发送消息,告知其需要进行graceful shutdown,worker进程会在连接处理完之后进行退出。 步骤3、经过一段时间之后,将会只会有新的worker进程处理新的连接。 注意,旧master进程并不会关闭它的listen socket;因为如果出问题后,需要回滚,master进程需要法重新启动它的worker进程。 步骤4、如果升级成功,则可以向旧master进程发送QUIT信号,停止老的master进程;如果新的master进程(意外)退出,那么旧master进程将会去掉自己的pid文件的.oldbin后缀。 什么是graceful shutdown 本文中的graceful shutdown是指server不再处理新的连接,但是进程不会立即退出,待所有连接断开后再退出进程。 总结一下在nginx 二进制文件热升级时用的命令 cd /usr/local/nginx cp nginx nginx_bak mv /data/nginx/nginx ./nginx #需要使用mv来更新二进制文件 ./nginx -t #尝试启动,查看其加载配置文件等初始化功能是否正常 netstat -anp | grep -E "80|443" | grep nginx #检查连接状态 kill -USR2 `cat /usr/local/nginx/nginx.pid` #升级nginx可执行文件,此时会有两组nginx master和worker进程 kill -WINCH `cat /usr/local/nginx/nginx.pid.oldbin` #新的可执行文件启动ok,且能够正常处理数据流,告知老的master进程去通知其worker进程进行优雅退出 ... kill -QUIT `cat /usr/local/nginx/nginx.pid.oldbin` #待所有的老的nginx worker进程优雅退出后(处理完连接),停止老的master进程 TODO:nginx还会有依赖的so文件的热升级–其实更应该属于后台进程的so文件热升级流程,我在使用它的时候也踩过坑–主要原因还是操作不规范,对so其加载运行原理不够熟悉导致 热升级 实际上,静态语言后端server有一套固定的热升级(单进程)流程,其基本流程如下: 若需要支持热升级的是多进程,那么nginx的热升级过程是最值得参考的 1、通过调用 fork/exec 启动新的版本的进程, 2、子进程调用接口获取从父进程继承的 socket 文件描述符重新监听 socket 3、在此过程中,不会对用户请求造成任何中断。 nginx的热升级流程也是类似,只不过由于nginx工作是多进程,故它会先启动新版本的一组master/worker进程;然后停止老的worker进程,让其不处理连接,由新的worker进程来处理连接;升级完毕后,即可退出老的master进程,热升级完成。 4、Nginx upstream中 backup备份服务器的作用 Nginx 的 upstream 配置的时候,可以配置备份服务器 backup。 upstream backend { server 192.168.198.128:8080 weight=1; server 192.168.198.128:8090 weight=4; server 192.168.198.128:8091 backup; } backup : marks the server as a backup server. It will be passed requests when the primary servers are unavailable.(标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。) 这意思就是,只有当你的服务器挂掉的时候才会使用备份服务器,正常情况下不会访问到备份服务器。 在所有正常服务器都挂掉时,系统依然高可用,这就是备份服务器的用处 #num0 INT(快速关闭)----是当用户键入时由终端驱动程序发送的信号。这是一个终止当前操作的请求,如果捕获了这个信号,一些简单的程序应该退出,或者允许自给被终止,这也是程序没有捕获到这个信号时的默认处理方法。拥有命令行或者输入模式的那些程序应该停止它们在做的事情,清除状态,并等待用户的再次输入。 TERM(快速关闭)----是请求彻底终止某项执行操作,它期望接收进程清除自给的状态并退出。 HUP---- 平滑启动,重新加载配置文件。 有两种解释: 1:他被许多守护进程理解为一个重新设置的请求。如果一个进程不用重新启动就能重新读取它的配置文件并调整自给以适应变化的话,那么HUP通常来触发这种行为。 2:HUP信号有时候又终端驱动程序生成,试图来"清除"("终止")跟某个特定终端相连的那些进程。例如:某个终端会话结束时,或者当调制解调器被挂断时,shell后台不接受HUP的信号的影响,有的用户可以使用nohup来模仿这种行为。 QUIT:从容关闭。 kill -HUP -> 平滑启动,重新加载配置文件 kill -QUIT -> 从容关闭(worker_processes) nginx热更新相关信号(kill命令) master进程相关信号 USR2 升级可执行文件 WINCH 优雅停止worker进程 QUIT 优雅停止master进程 worker进程相关信号 TERM, INT 快速退出进程 QUIT 优雅停止进程