我们都知道nginx的命令执行格式是nginx 参数
,参数主要有如下的:
-?, -h |
打印帮助。 |
---|---|
-v |
打印版本。 |
-V |
打印 NGINX 版本、编译器版本并配置参数。 |
-t |
不要运行,只测试配置文件。NGINX 检查配置的语法是否正确,然后尝试打开配置中引用的文件。 |
-q |
在配置测试期间抑制非错误消息。 |
-s signal |
向主进程发送信号:stop(暴力停止)、quit(优雅退出)、reopen(重新打开日志)、reload(重新加载)。(版本 >= 0.7.53) |
-p prefix |
设置前缀路径(默认:/usr/local/nginx/ )。(版本 >= 0.7.53) |
-c filename |
指定 NGINX 应该使用哪个配置文件而不是默认配置文件。 |
-g directives |
设置全局指令。(版本 >= 0.7.4) |
其他的没啥好讲的,我们只讲一个东西nginx -s 参数
,如果你以yum方式安装过部分非官方的nginx你就会发现他们自带了日志切割的功能,nginx本身当然是没有这个功能的,我们经过分析发现一般是使用系统自带的logrotate
实现的。我们需要了解的是,所谓的日志切割本质上就是把现有的日志重命名为备份日志,让nginx写入到一个新的文件里面去(但是如果你自己直接重命名你就会发现一个问题,日志文件虽然被重命名了,但是日志还是往老的文件里面写,当然原因也很简单:程序是通过文件描述符去操作的,你重命名不会改变这种关系,这个时候你需要让nginx重新打开即nginx -s reopen
)。
这个时候重点来了,我们查看logrotate
的配置文件,有如下一行:kill -USR1 'cat /var/run/nginx.pid'
,是不是跟你想象中不同,kill不是杀死程序吗?我们平常大部分也是这么做的,但是其实不然,我们也可以通过kill命令向程序发送某些信号。比如根据nginx程序的定义kill -USR1 pid
就跟nginx -s reopen
是等效的。其他的如下表:
TERM, INT | Quick shutdown |
---|---|
QUIT | Graceful shutdown |
KILL | Halts a stubborn process |
HUP | Configuration reloadStart the new worker processes with a new configurationGracefully shutdown the old worker processes |
USR1 | Reopen the log files |
USR2 | Upgrade Executable on the fly |
WINCH | Gracefully shutdown the worker processes |
ok,有了前面的知识储备,我们就可以进行后面的工作了。如何优雅地不停机的升级nginx?
假设nginx正在提供服务,一切正常,现在我们想要对nginx进行热升级,大致步骤如下:
- 最重要的一步,备份。
- 下载新版本的nginx,根据老版本的编译选项,对新版本完成编译的步骤,只对新版本进行编译操作,不执行安装操作,换句话说就是,只执行make命令,不执行make install命令,完成编译操作后,即可获取到我们需要的新版本的二进制文件,之后,我们需要根据实际情况判断哪些文件需要被替换,此处描述的”根据情况判断”在后文中会有解释,先不用纠结,此处假设,根据情况判断后,只需要替换nginx二进制文件。
- 确定已经备份老版本的nginx二进制文件,以防万一,用编译好的新版本的nginx二进制文件替换老版本的nginx二进制文件,此时老版本的nginx仍然在内存中正常运行,所以不用担心,我们替换的只是硬盘中的二进制文件,做好备份即可。
- 对nginx的master进程(正在运行的老版本的master进程)发送USR2信号,老版本的master进程收到信号后,会通过新版本的二进制文件启动新版本的master进程,新版本的master进程会启动新版本的worker进程,此时新老版本的nginx进程同时存在。
- 向老版本的master进程发送WINCH信号,以便先优雅的停止老版本的worker进程,新的请求会被新版本的worker进程处理,此时老的master进程仍然存在,留下老的master进程是为了以防万一,以便随时回滚,此时老版本的master进程、新版本的master进程和新版本的worker进程同时存在,升级过程暂且完毕。
- 如果升级后万一出现问题,则可以随时进行回滚,由于老版本的master进程并未停止,所以我们可以向老的master进程发送HUP信号,即可通过老版本的master进程重新生成老版本的worker进程,当老版本的worker进程重新被拉起后,即可向新版本的master进程发送QUIT信号,以便优雅的关闭新版本的nginx进程,回滚操作完毕。
大概的命令如下:
|
|