在Web服务运维中,Nginx的升级是一个常见且重要的任务。随着Nginx版本的不断更新,新功能、性能优化和安全修复不断被引入。然而,在生产环境中,服务的中断是不被接受的。因此,Nginx的平滑升级技术显得尤为重要。本文将详细介绍Nginx平滑升级的原理、流程、注意事项及实践案例。
Nginx平滑升级的主要目的是在不影响用户访问的情况下,实现Nginx的版本升级或配置更新。这种升级方式可以确保服务的连续性和稳定性,避免因升级导致的服务中断和数据丢失。
平滑升级可以确保在整个升级过程中不中断正在处理的请求,这对于需要提供高可用性和无缝用户体验的服务来说至关重要。
在升级期间,Nginx可以继续处理来自用户的请求,而不需要暂停或重启整个服务,这对于在线业务和关键应用来说至关重要。
平滑升级可以在后台进行,对用户来说是透明的,用户不会察觉到系统正在进行升级,可以继续正常使用服务而不受影响。
平滑升级允许管理员在新旧配置之间平稳过渡,确保新的配置在启用后立即生效,而不会导致服务中断。
Nginx默认工作在多进程模式下,即主进程(master process)启动后完成配置加载和端口绑定等动作,然后fork出指定数量的工作进程(worker process)。这些子进程会持有监听端口的文件描述符(fd),并通过在该描述符上添加监听事件来接受连接(accept)。Nginx主进程在启动完成后进入等待状态,监听系统信号以进行相应操作。
平滑升级的关键在于利用Nginx主进程对新旧版本的控制能力,通过发送特定的系统信号来实现新旧进程的平稳过渡。
首先,确保你已经下载并上传了新版的 Nginx 源码包到服务器。
[root@www ~]# ls nginx-1.*
nginx-1.10.1.tar.gz nginx-1.6.2.tar.gz
在升级之前,首先需要查看当前 Nginx 的编译选项。确保在编译新版本时使用相同的选项。
[root@www ~]# nginx -V
输出中会包含类似以下内容的编译选项:
。。。。。。省略部分信息。。。。。。。
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-file-aio --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_ssl_module --with-pcre
解压并编译新版本的 Nginx 源码,注意 不要 执行 make install
,以避免覆盖旧版。
[root@www ~]# tar zxf nginx-1.10.1.tar.gz -C /usr/src/
[root@www ~]# cd /usr/src/nginx-1.10.1/
# 这是上边查看的编译参数
[root@www nginx-1.10.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-file-aio --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_ssl_module --with-pcre && make
备份旧版的 Nginx 二进制文件,并将新编译的二进制文件替换到相应目录下。
[root@www nginx-1.10.1]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
[root@www nginx-1.10.1]# cp objs/nginx /usr/local/nginx/sbin/
确保新的 Nginx 二进制文件能够正确读取和解析现有的配置文件。
[root@www nginx-1.10.1]# 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
向旧的 Nginx 主进程发送 USR2
信号,这会启动新的 Nginx 主进程及其工作进程,同时旧版 Nginx 进程依然存在并继续处理现有请求。
[root@www ]# ps aux |grep nginx |grep -v grep
[root@www ]# kill -USR2 <旧版主进程PID>
确认新的 Nginx 主进程已启动:
[root@www ]# ps aux |grep nginx |grep -v grep
举例
[root@www ]# ps aux |grep nginx |grep -v grep
root 6059(老版本主进程) 0.0 0.2 45000 1032 ? Ss 13:03 0:00 nginx: master process nginx
nginx 6060 0.0 0.3 45432 1624 ? S 13:03 0:00 nginx: worker process
[root@www ]# kill -USR2 6059
[root@www ]# ps aux |grep nginx |grep -v grep
root 6059 0.0 0.2 45000 1196 ? Ss 13:03 0:00 nginx: master process nginx
nginx 6060 0.0 0.3 45432 1624 ? S 13:03 0:00 nginx: worker process
root 8516(新版本主进程) 0.0 0.5 45156 2744 ? S 13:05 0:00 nginx: master process nginx
nginx 8517 0.0 0.3 45600 1668 ? S 13:05 0:00 nginx: worker process
向旧版 Nginx 主进程发送 WINCH
信号,这会逐步关闭旧版 Nginx 的工作进程,而新的 Nginx 进程将接管所有请求。
[root@www ~]# kill -WINCH <旧版主进程PID>
举例
[root@www ~]# kill -WINCH 6059
[root@www ~]# ps aux |grep nginx
root 6059 0.0 0.2 45000 1200 ? Ss 13:03 0:00 nginx: master process nginx
root 8516 0.0 0.5 45156 2744 ? S 13:05 0:00 nginx: master process nginx
nginx 8517 0.0 0.3 45600 1668 ? S 13:05 0:00 nginx: worker process
root 8526 0.0 0.1 103256 836 pts/0 S+ 13:14 0:00 grep nginx
确认新版本运行稳定后,可以通过发送 QUIT
信号终止旧版 Nginx 主进程。
[root@www ~]# kill -QUIT <旧版主进程PID>
举例
[root@www ~]# kill -QUIT 6059
[root@www ~]# ps aux |grep nginx
root 8516 0.0 0.5 45156 2744 ? S 13:05 0:00 nginx: master process nginx
nginx 8517 0.0 0.3 45600 1668 ? S 13:05 0:00 nginx: worker process
root 8531 0.0 0.1 103256 836 pts/0 S+ 13:16 0:00 grep nginx
验证 Nginx 版本号以确认升级成功。
[root@www ~]# nginx -v
nginx version: nginx/1.10.1
同时,可以通过访问 Nginx 服务验证新版本是否正常运行。
[root@www ~]# curl -I localhost
如果需要回滚到旧版 Nginx,可以向旧的 Nginx 主进程发送 HUP
信号,这会重新启动旧版的工作进程,随后可以终止新版本的 Nginx 进程。
[root@www ~]# kill -HUP <旧版主进程PID>
[root@www ~]# kill -QUIT <新版主进程PID>