1. 引言
前一篇文章介绍了用流量复制来验证系统的正确性,那么验证完我们就直接用新版本替换掉老版本吗?
大部分确实会这么做,但对于关键的系统这样直接替换还是不稳妥,下面以一次我们实际做过的分流器重构为例,来描述下为何我们需要如此谨慎,如下图示意:
- 这是一个视频会议产品,有A、B、C、D多套环境分别服务不同的客户群;
- 分流器对外承接所有用户的入会请求,对内将流量分发至不同的会议环境;
不难发现,这是整个会议产品的主业务入口,一旦出问题,会直接影响系统的可用性。
那有什么方法能降低上线风险吗?
有,就是我们今天这篇文章要讨论的主题:平滑上线。
2. 思路
日常普通版本上线,基本就是在原来旧版本的机器上直接用新版本覆盖部署,线上用户流量从旧版本全部一刀切到新版本上。
这种模式如果用于大版本的上线,就会面临两个风险:
- 如果新版本出现问题,系统所有用户都会受影响,影响面很大;
- 如果问题严重需要回退,只能再重新部署老版本,包括程序、配置等一系列需要还原,速度太慢;
那如何解决呢?
要规避这两个风险,我们也可以从两方面思考:
- 如果新版本只是承担部分流量,出问题时是不是就能缩小影响面?
- 如果老版本不下线,和新版本共存,是不是就可以在出问题时快速恢复?
基于这个思路,我们制定了分多步走的上线方案:
- 新版本独立部署,和老版本共存
- 逐步切流,稳步替换
- 老版本下线,新版本替换掉老版本
下面分别阐述。
2.1 新版本部署
- 在新的机器上独立部署新版本,老系统不动,即让新版本和老版本在线上共存(如下图示意)。
- 对新版本系统作一些基本的验证,例如前一篇文章提到的流量复制。
新版本虽然在线上跑起来了,但并没有承担任何流量,所以这一步还不能称为上线,只能叫作部署,流量还是全部在老版本上。
2.2 逐步切流
逐步切流需要先找一个能够按比例来分配流量的方法,所幸
反向代理基本都支持按权重来配置负载均衡,我们老系统用的是Apache,就能拿Apache示意如何配置:
ProxyRequests Off # 关闭正向代理
<Proxy balancer://mycluster> # 定义一个名为mycluster的负载均衡器
BalancerMember http://newsystem.com loadfactor=10 # 定义负载均衡器的成员: 新系统,承担10%的流量,
BalancerMember http://oldsystem.com loadfactor=90 # 定义负载均衡器的成员:老系统,承担90%的流量
</Proxy>
ProxyPass / balancer://mycluster # 将所有请求转发到mycluster,协议可自定义,与Proxy中保持一致即可
ProxySet lbmethod=bytraffic # 指定工作方式为按流量分配,即按成员权重分配负载
其中,loadfactor就是用于定义负载权重,值越大负载越高。
有了这个负载权重的配置支持后,我们只要逐步调整新、老系统的权重比例,就能完成这个上线过程。
以上面的分流器为例,整个上线的切流步骤大概如下:
- 第1次,只切5%的少量流量到新版本上,95%的大部分流量还是在老系统上,维持3到4天,期间可以通过日志等信息来观察运行情况;
- 第2次,切20%的流量到新版本上,80%的流量还是由老版本处理,也维持3到4天观察运行情况;
- 第3次,切50%的流量到新版本上,新、老版本流量各一半,同样维持几天观察运行情况;
- 第4次,切100%的流量到新版本上,老版本不再承担流量。
切流如下图示意:
如果中间发现问题,可以随时调整权重将流量全部恢复到老版本上,只不过修复问题后可能需要重复走上述步骤。
走完这个过程后,新系统权重由0变为100、老系统权重由100变为0,新系统基本就完成了上线,从流量层面实现了对老版本的替代。
但是,老版本也没下线,所以我们这个上线过程还没结束。
2.3 老版本下线
在我们这个例子上中,老版本下线分为两部分:
- 老分流器服务的下线;
- 反向代理Apache的下线;
2.3.1 老分流器服务下线
新分流器已经切走了全部流量,我们的老分流器能直接下线吗?
恐怕还不能,至少还不太稳妥。原因在于:
- 我们是基于用户对系统的使用反馈来发现问题,但用户反馈问题不一定及时;
- 有些用户是低频用户,可能会出现系统刚上线的那几天,用户正好没使用,过了十天半个月才来使用;
- 上线完成的标准并不是流量切分完毕,而是系统能在线上稳定运行一段时间,有些系统问题是需要时间才能发现的;
基于此考虑,我们可以将老分流器热备一段时间(例如一个月),期间它不承担任何流量,如下图示意:
如果这段时间仍然没发现问题,新系统基本就算稳定上线,老系统可以下线将机器释放出来了。
2.3.2 反向代理的下线
这里的反向代理指的是上图中提到的apache,细心的同学能观察到,新分流器是使用基于nginx的Openresty开发,本身就有反向代理的全部功能,并且性能还优于Apache。不论是出于缩短请求链路长度考虑,还是出于节省机器资源考虑, 都没有理由继续保留Apache。
与老分流器服务的下线稍微有点不同,Apache所在机器是系统对外域名解析的地址,我们需要多做一步域名解析的调整,如下图示意:
域名解析修改的生效可能需要一点时间,同之前老分流器服务下线一样,可以将Apache保留个几天,再回收机器。
小结
本文以一个典型案例分流器上线为例,介绍了按权重比例逐步切流并将系统平滑推上线的一种思路,它对于诸如系统重构、大版本优化之类项目的最终落地上线,往往能起到关键的最后一棒助力。
上面提到的权重比例调整是以Apache为例,在Nginx中基本也类似,示例如下:
# weight表示权重,比例为:第一个服务访问5次,第二个服务访问1次
upstream server_list{
server localhost:8080 weight=5;
server localhost:9999 weight=1;
}
重构优化属于研发工作中偏难的一类,不仅仅对梳理、设计、编码的能力有要求,它的上线难度也是被很多人忽视的一环,曾见过不少有意义的项目到了临上线一脚却最终止步不前。
个人看法是,我们既不能因噎废食、怕担风险,就躲开重构优化这类工作;也不能全凭侥幸心理,拿系统的可用性来赌自己的运气。遇到风险还是要正面对待,积极寻找方法,当一心想要解决问题时,办法总会比困难多。
最后祝愿每一位开发者的项目都能稳定上线。
参考阅读:
- 流量复制:https://blog.csdn.net/xiaojia1001/article/details/133903910