概述

本文主要介绍如何在 nginx 运行中,不停止服务的情况下升级 nginx 的版本

前置准备

系统环境:centos7.9

已安装软件:nginx-1.18.0(yum安装)

nginx信号控制

nginx 能够通过信号来进行控制,使用 kill -信号 master进程pid master进程pid 可以使用命令 ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)' 获取,或者查看 nginx.pid 文件内容获取。

信号 说明
TERM, INT 强制退出 master 进程和 work 进程,直接丢弃未完成的请求
QUIT 平滑退出 master 进程和 work 进程,处理完已接收的请求,不接收新请求
HUP 重新读取配置文件,开启新 work 进程,平滑的关闭旧 work 进程
USR1 开启新的日志文件
USR2 升级 nginx 可执行文件
WINCH 平滑的退出 work 进程,配合 USR2 实现平滑升级

work 进程也可以使用信号控制,本文不做介绍,自行查看官方文档

平滑升级步骤

平滑升级

  1. 首先把旧的 nginx(yum安装的是 /usr/sbin/nginx)执行文件进行备份,改名为 nginx-1.18.0.bak
  2. 将新版本的 nginx 解压编译,并将其中 objs/nginx 代替旧的 nginx 文件。
  3. 向旧的 master 进程发送 USR2 信号,nginx 将会创建新的 master 进程和新的 worker 进程。
  4. 向旧的 master 进程发送 WINCH 信号,停止旧的 worker 进程。
  5. 如果升级成功,向旧的 master 进程发送 QUIT 信号,停止旧的 master 进程;如果升级失败,请参照下面步骤执行回滚操作。

回滚

  1. 向旧的 master 进程发送 HUP 信号,重新开启旧的 worker 进程。
  2. 向新的 master 进程发送 QUIT 信号, 停止新的 master 进程。

开始升级

本文是将 yum 安装的 nginx-1.18.0 升级为 nginx-1.22.0

下载源码包

下载地址:https://nginx.org/en/download.html

编译可执行文件

创建 /usr/local/server 文件夹,然后上传下载的源码包到此目录。

[root@localhost ~]# mkdir -p /usr/local/server

查看旧 nginx 的配置参数

image-20221010110004044

编译

[root@localhost ~]# cd /usr/local/server
[root@localhost server]# tar zxvf nginx-1.22.0.tar.gz
[root@localhost server]# cd nginx-1.22.0
# 使用与旧 nginx 相同的配置
[root@localhost nginx-1.22.0]# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
# 编译,千万不要执行 make install, 否则配置文件等都会被覆盖
[root@localhost nginx-1.22.0]# make

如果编译中出现 C compiler cc is not found 错误信息,需要安装c++, 运行 yum install gcc

如果编译中出现 PCRE 错误信息,运行 yum install pcre-devel

如果编译中出现 openssl 错误信息,运行 yum install openssl openssl-devel

替换可执行文件

# 先备份旧的
[root@localhost nginx-1.22.0]# mv /usr/sbin/nginx /usr/sbin/nginx-1.18.0.bak
# 替换
[root@localhost nginx-1.22.0]# cp objs/nginx /usr/sbin/nginx

开始平滑升级

查看旧 master 进程的 pid,可以看到是 9927

[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
9927 1 root 0.0 46464 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
9928 9927 nginx 0.0 46856 ep_pol nginx: worker process
16746 9799 root 0.0 112812 - grep -E --color=auto (nginx|PID)

发送 USR2 信号, 生成了新的 master 进程,pid 是 16747, 且父进程是旧 master 进程。

[root@localhost nginx-1.22.0]# kill -USR2 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
9927 1 root 0.0 46464 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
9928 9927 nginx 0.0 46856 ep_pol nginx: worker process
16747 9927 root 0.0 46516 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16748 16747 nginx 0.0 46916 ep_pol nginx: worker process
16750 9799 root 0.0 112816 pipe_w grep -E --color=auto (nginx|PID)

发送 WINCH 信号, 可以看到旧 master 进程 的 work 进程 9928 已经关闭了

[root@localhost nginx-1.22.0]# kill -WINCH 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
9927 1 root 0.0 46464 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16747 9927 root 0.0 46516 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16748 16747 nginx 0.0 46916 ep_pol nginx: worker process
16777 16759 root 0.0 112812 - grep -E --color=auto (nginx|PID)

验证升级是否成功

通过 curl 访问 nginx 的 index.html 页面(或者浏览器的控制台查看),可以看到 Server 显示为 nginx/1.22.0,表示升级成功

[root@localhost nginx-1.22.0]# curl -i 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Wed, 09 Mar 2022 11:16:43 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 29 Oct 2020 15:25:17 GMT
Connection: keep-alive
ETag: "5f9adedd-264"
Accept-Ranges: bytes

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

成功后关闭旧的 master 进程

[root@localhost nginx-1.22.0]# kill -QUIT 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
16747 1 root 0.0 46516 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16748 16747 nginx 0.0 46916 ep_pol nginx: worker process
16833 16759 root 0.0 112812 - grep -E --color=auto (nginx|PID)

参考链接

官方文档:https://nginx.org/en/docs/control.html#upgrade

nginx平滑升级:https://www.361shipin.com/blog/1534406139729412096#nginx_68