什么是热部署
所谓热部署,能够在不重启也就是不会打断nginx处理请求的情况下更新配置文件,升级版本,更换日志文件。
nginx热部署流程
修改配置文件nginx.conf后,重新生成新的worker进程,新的请求过来后由新的worker进程来处理,至于老的worker进程,等把那些以前的请求处理完毕后,kill掉即可。
nginx热部署步骤
以nginx1.12升级到nginx1.14为例
1、安装并启动Nginx1.12,由下面可以看到nginx1.12正确运行
wget https://nginx.org/download/nginx-1.12.2.tar.gz -P /opt/software
tar zxvf nginx-1.12.2.tar.gz
cd nginx-1.12.2
./configure --prefix=/root/nginx
make && make install
[root@slave2] ~/nginx$ ps -ef |grep nginx
root 33691 1 0 10:08 ? 00:00:00 nginx: master process sbin/nginx
nobody 36287 33691 0 10:29 ? 00:00:00 nginx: worker process
root 38831 31104 0 11:04 pts/0 00:00:00 grep --color=auto nginx
[root@slave2] ~/nginx$ curl localhost
[root@slave2] ~/nginx$ sbin/nginx -v
nginx version: nginx/1.12.2
2、编译nginx1.14版本,注意这里只需要make,不用多此一举make install,因为我们只需要编译好的新版本的nginx二进制文件
configure/make/make install的作用
- make是用来编译的,它从Makefile中读取指令,然后编译。
- make install是用来安装的,它也从Makefile中读取指令,安装到指定的位置。
- AUTOMAKE和AUTOCONF是非常有用的用来发布C程序的东西。
wget https://nginx.org/download/nginx-1.14.2.tar.gz -P /opt/software
tar zxvf nginx-1.14.2.tar.gz
cd nginx-1.14.2
./configure --prefix=/root/nginx
make
[root@slave2] /opt/software/nginx-1.14.2/objs$ ls
autoconf.err nginx ngx_auto_config.h ngx_modules.c src
Makefile nginx.8 ngx_auto_headers.h ngx_modules.o
[root@slave2] /opt/software/nginx-1.14.2/objs$ ./nginx -v
nginx version: nginx/1.14.2
3、备份nginx1.12二进制文件
[root@slave2] /opt/software/nginx-1.14.2/objs$ cd /root/nginx/sbin/
[root@slave2] ~/nginx/sbin$ ls
nginx
[root@slave2] ~/nginx/sbin$ cp nginx nginx12
4、复制新版本Nginx1.14二进制文件到现有Nginx工作目录。
[root@slave2] ~/nginx/sbin$ cp /opt/software/nginx-1.14.2/objs/nginx /root/nginx/sbin/
cp: overwrite ‘/root/nginx/sbin/nginx’? y
[root@slave2] ~/nginx/sbin$ ls
nginx nginx12
[root@slave2] ~/nginx/sbin$ ./nginx -v
nginx version: nginx/1.14.2
5、给当前的Nginx发送USR2信号
在前面的Nginx命令行我介绍了通过kill信号来控制Nginx的行为,USR2
这个信号就是来传递热部署的信号,我将这个信号传递给master进程。
[root@nginx ~]# ps -ef | grep nginx
root 11589 1 0 21:30 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx
nobody 11590 11589 0 21:30 ? 00:00:00 nginx: worker process
root 11652 8971 0 21:41 pts/0 00:00:00 grep --color=auto nginx
[root@nginx ~]# kill -USR2 11589
此时Nginx会新开启一个master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
[root@nginx ~]# ps -ef | grep nginx
root 11589 1 0 21:30 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx
nobody 11590 11589 0 21:30 ? 00:00:00 nginx: worker process
root 11653 11589 0 21:42 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx
nobody 11654 11653 0 21:42 ? 00:00:00 nginx: worker process
root 11660 8971 0 21:46 pts/0 00:00:00 grep --color=auto nginx
6、停止旧的worker进程
这一步是平滑升级的最后一步,我们给旧的master进程发送WINCH信息,让其从容关闭工作进程。
[root@nginx ~]# kill -WINCH 11589
[root@nginx ~]# ps -ef | grep nginx
root 11589 1 0 21:30 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx
root 11653 11589 0 21:42 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx
nobody 11654 11653 0 21:42 ? 00:00:00 nginx: worker process
root 11662 8971 0 21:49 pts/0 00:00:00 grep --color=auto nginx
从上面输出信息我们可以到旧的worker已经关闭了,但是旧的master进程没有关闭,实际上到这一步所有的请求已经全部切换到新升级后的Nginx服务了,那么此时旧的master进程不会有任何工作。查看版本也是最新的版本,升级完成。
注:如果在版本升级完成后,没有任何问题,需要关闭老的master进程的话,可以使用下面的命令:
kill -QUIT old_master_PID
7、版本回滚
在上面的结果中,我们也能看到老的master进程是一直存在,在没有手工关闭前,它是不会自已关闭的,这种设计是有好处的,好处就是为了升级新版本后,如果出现问题能及时快速的回滚到上一个稳定版本。
[root@nginx ~]# ps -ef|grep nginx
root 6324 1 0 09:06 ? 00:00:00 nginx: master process /usr/local/nginx-1.12.2/sbin/nginx
root 6340 6324 0 09:12 ? 00:00:00 nginx: master process /usr/local/nginx-1.12.2/sbin/nginx
nobody 6341 6340 0 09:12 ? 00:00:00 nginx: worker processroot 6350 1244 0 09:23 pts/0 00:00:00 grep --color=auto nginx
[root@nginx ~]# cd /usr/local/nginx-1.12.2/sbin/
[root@nginx sbin]# mv nginx nginx-1.14.2
[root@nginx sbin]# mv nginx-1.12.2 nginx
[root@nginx sbin]# kill -USR1 6324
root@nginx sbin]# ps -ef|grep nginx
root 6324 1 0 09:06 ? 00:00:00 nginx: master process /usr/local/nginx-1.12.2/sbin/nginx
root 6340 6324 0 09:12 ? 00:00:00 nginx: master process /usr/local/nginx-1.12.2/sbin/nginx
nobody 6341 6340 0 09:12 ? 00:00:00 nginx: worker process
root 6355 1244 0 09:24 pts/0 00:00:00 grep --color=auto nginx
[root@nginx sbin]# ./nginx -v
nginx version: nginx/1.12.2
怎么添加模块或编译选项
以添加echo-nginx-module为例
1、如果已安装Nginx,需要先查看当前安装版本的编译参数:
$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.12.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module
其中configure arguments
这个参数是非常重要的,我们在后面安装Lua模块的时候,需要以这个为基础,增加新的参数。
2、获取echo-nginx-module
我们下载最新稳定版(截止到2018-12-23),并解压,不用安装:
$ cd /opt
$ wget https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz
$ tar zxvf v0.61.tar.gz
3、重新编译Nginx
Nginx编译参数配置:
$ cd /opt/nginx-1.12.2/
$ ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --add-module=/opt/echo-nginx-module-0.61
这里因为已经安装了Nginx,所以这里的参数是从Nginx -V
的输出里获取的,并追加了新的参数:
--add-module=/opt/echo-nginx-module-0.61
运行上面的./configure
后进行编译安装:
$ make -j2
$ make install
make install
后,会覆盖之前安装的Nginx。
4、重启nginx
sbin/nginx -s stop
sbin/nginx
注意:
改变Nginx
二进制文件,需要停止重启。普通配置更新则只需reload
即可:
除了以上静态的编译模块,还有一种动态的添加模块的方式。
编译动态模块
Nginx1.9.11之后增加了动态添加模块的功能
。echo-nginx-module
支持以动态模块方式加载,详见:https://github.com/openresty/echo-nginx-module#installation 。
$ cd /opt/nginx-1.12.2/
$ ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --add-dynamic-module=/opt/echo-nginx-module-0.61
$ make -j2
$ make install
相比静态编译,参数--add-module
改成了--add-dynamic-module
。
编译成功后,会把模块安装在nginx/modules/
目录。查看:
$ ls /usr/local/nginx/modules/
ngx_http_echo_module.so
然后在nginx.conf
中通过load_module指令载入,实现动态调用模块:
load_module /usr/local/nginx/modules/ngx_http_echo_module.so;
注意:
load_module
指令不能放在http{}
里面:
worker_processes 1;
load_module xxx;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
}
动态添加模块的好处是不用重启启动Nginx,可以直接使用nginx -s reload
热重启就行了。
查看默认已安装的模块?(存疑)
进入解压后的nginx源码目录下的auto目录中,
cat options |grep "YES"
如何查看已安装且已加载的模块?
如何查看自定义的模块?
nginx -V
关于nginx中的信号
kill -USR1 等于 nginx -s reopen 这个信号量本来就是用于重新读取日志文件的
kill -USR2 等于 nginx -s reload
reload 和 reopen 的行为相差很大,reopen 仅仅检查日志文件,reload 会重载配置,并启动新 worker,关闭旧 worker
nginx -s stop和-s quit有什么区别?
quit退出是一个优雅的关闭. Nginx在关机前完成为打开的连接提供服务
stop停止是快速关闭,在服务连接之间终止