背景介绍

所谓的平滑升级,在实际生产中有些场景下会用到啊,比如说你现在是个电商业务,或者是一个不能停止的一个互联网应用。

假设说游戏。那你想现在我想涉及到一个版本的升级,我原来的那个版本可能有bug。有严重的安全风险。

那现在我为了。解决这个版本带来的问题,我就要升级。那这个升级的话,我们因为现在业务正在对外提供服务,我不能停了,再升级停了,再升级的话,影响业务,尤其有些互联网业务,24小时在提供。

如何想做升级是不是就把这个软件重新编译,重新把所有的文件啊?尤其那个nginx二进制文件给替了就行。啊,这个能停的话很简单,重装一遍就完了,用新版本给它替换了就行了

所以我们这个平滑升级听起来还是挺重要的啊,就是用户在不影响访问的情况下,你就在用户无感知的情况下,他就给他升级了,用户感觉不到。


平滑升级4阶段

要做到下面这4个阶段

Nginx平滑升级_平滑升级


一个是master进程,一个worder进程,这两个进程都对应的老版本就是最初的状态。那么。接着我们要升级,

那么就进入到第二个阶段,第二个阶段我们看到这个图画的还是很明确的啊,那么有两个matter 一新一旧,红的是新版本出现。黄的是旧版本,同时他们各有各的什么worker进程,都有worker进程了。

Nginx平滑升级_平滑升级_02

也就是说我现在相当于两套新旧版本都并存

当然并存完了以后呢?咱们接着进入到第三个阶段,第三个阶段先把旧版本的worker进程给它关掉。

当然,把这个关的话呢,存在一个问题,就是你如果你直接把worker进行关了, 是存在问题的,因为人家有用户,是不是有可能正在访问?

那正在访问的时候,你这个worker进程,你贸然直接关了的话,那相当于断开这个连接了,这就不叫平滑升级了。

所以我们如果有用户。正在访问这个旧版本的worker进程。那我这儿不会断开。我只是把这个没人反馈的给他kill了。

Nginx平滑升级_平滑升级_03

而我们WEB服务呢?它的访问通常时间是不会特别长的啊,那所以过一段时间是不是这个worker进程也就没有人访问了?

那我就把一个一个的worker进程里面全关掉,那就最终就成了一个只有一个什么呢?老的版本的master进程。

那这时候呢,用户再发起请求,大家想到了吗?啊,我们用户发起请求,现在只能由谁来处理了?新版本的worker进程.

所以在这种情况下,已经让用户已经访问新版本了,就在这个状态下已经访问新版本了,不过呢,老版本的master还在。新版本接受用户的访问了啊,是这样一个状态。那在这种状态下。事实上,已经完成了升级的过程了,只不过就是我们老版本还留着。

当然,这个过程到此实际上已经升级差不多了,但是我们进入不进入到最后一个阶段,完全升级呢,这个还是要考量的。因为在这个过程中,我们有用户已经得到新版本了,但是也可能他访问的时候,这个新版本有存在不兼容啊,存在各种问题呀。

也有可能用户抱怨了你这个新版本升级完各种问题。不好,能不能还回到主版本哎?实际上我们这块还来得及,因为我们老版本还没有彻底杀掉,所以这时候呢.

我们如果版本新的有问题,我们还是可以回来的。还可以再回到。最初的状态,它可以撤销,还可以撤销,当然也可能我们观察一段时间,发现新版本能够很稳定运行,没有问题。这时候我们就可以彻底的进行升级,进入到最后一个阶段。

Nginx平滑升级_平滑升级_04

实现升级

当前机器的nginx的版本是nginx1.24

Nginx平滑升级_平滑升级_05

启动服务,然后确定是80端口已经打开

Nginx平滑升级_nginx_06

我们新找一台机器访问,发现是没问题的

Nginx平滑升级_平滑升级_07


为了模拟这个升级过程,那我们现在就限速。limit,然后我们现在。呃,慢一点,让他去慢慢访问。

Nginx平滑升级_平滑升级_08


官方下载版本

Nginx平滑升级_nginx升级_09

解压缩这个新版本

[root@ubuntu22 ~]#tar xf nginx-1.25.3.tar.gz -C /usr/local/src/

Nginx平滑升级_nginx_10


进入到新的目录下,来进行编译

Nginx平滑升级_nginx_11


这是编译用到的模块

[root@ubuntu22 nginx-1.25.3]#./configure --prefix=/apps/nginx 
--user=nginx --group=nginx --with-http_ssl_module 
--with-http_v2_module --with-http_realip_module 
--with-http_stub_status_module --with-http_gzip_static_module 
--with-pcre --with-stream --with-stream_ssl_module 
--with-stream_realip_module


我们在执行make,来编译

Nginx平滑升级_nginx升级_12


等它编译完成以后,它会生成一个叫objs的一个子目录,那个编辑生成的新版本就放在objs那个子目录上。

Nginx平滑升级_nginx_13


我们来看这个版本

Nginx平滑升级_nginx_14


先备份旧版本

[root@ubuntu22 nginx-1.25.3]#cp  -f /apps/nginx/sbin/nginx /opt/

Nginx平滑升级_nginx升级_15


我们把新版文件复制过去

[root@ubuntu22 nginx-1.25.3]#cp -f objs/nginx 
/apps/nginx/sbin/nginx

Nginx平滑升级_平滑升级_16


启动新版本

我们来看一下旧版本的nginx 的id

Nginx平滑升级_nginx_17


使用下面这个命令来升级

[root@ubuntu22 nginx-1.25.3]#kill -USR2 
`cat /apps/nginx/run/nginx.pid`

Nginx平滑升级_nginx_18

这时候我们一执行,你将发现你的系统中将新旧两个版本同时存在

然这时候呢,相当于我们又两个worker进程了吧?一个是老版本的worker进程,一个是新版本的worker进程是吧?那现在我访问的话,到底是由谁来提供服务?如果我们现在访问的话。

我们看这边的访问一直没断啊,看到没有用户的访问是不是不受影响

Nginx平滑升级_nginx升级_19


那现在我们就访问一下。呃,我们看一下。哪个版本?有新有旧啊,有新有旧,看到没有? 也有两个版本并存,

Nginx平滑升级_nginx升级_20


在执行这个命令

给这个应该是老版本的,  这个master进程发言的话就是要平滑关掉它的worker子进程

[root@ubuntu22 nginx-1.25.3]#kill -SIGWINCH
`cat /apps/nginx/run/nginx.pid.oldbin`

Nginx平滑升级_nginx_21

我们现在,访问的都是新版本了

Nginx平滑升级_平滑升级_22


到此就完成了