[关闭]
@gaoxiaoyunwei2017 2017-09-18T15:37:40.000000Z 字数 8630 阅读 628

微信高效运维之路 --- 吴磊

北哥


今天的主题主要是关于弹性伸缩,扩容和缩容这些方面。
image.png-49.6kB

微信业务量增长的时候,其实我们比较关心的是效率。前期可能两三个月就涨了1倍的量,我们怎么能够保证我们的运营效率是跟得上的。后期可能主要是关心成本。我们在2014年以后增长有点放缓,所以主要的精力会在成本这个方面。

分为四块来说:
image.png-117.8kB

一. 运营规范

1.1 配置文件规范

image.png-173.5kB

先来看配置文件规范,我们前期花了比较多的精力。可能整个系统设计比较复杂,最开始都会有一些配置管理工程师专门来处理,后期我们把这块搞得比较规范了。

配置文件规范分为下面几项:

同一服务下同一版本的多个实例,在所有环境下配置 文件的md5都严格一致。

1.2 名字服务规范

image.png-128.3kB

名字服务这块比较重要,分三层:

服务伸缩是运维工程,独立于研发的变更发布。

接入层和逻辑层,都是类似的实现,我们内部根据我们的业务特性做了一些业务开发。

存储层跟QQ有点不一样,QQ好像是逻辑层和存储层都是用同一个名字服务实现,我们在存储层这里还没有做这方面的配置。

我们现在存储层跟逻辑层隔得比较开,在涉及到数据的方面,我们差不多可以认为是运维能够配置的方式,但是又不完全是能够配置,用那些辅助脚本来配置。

服务伸缩是运维工程,我们不希望在服务伸缩时还考虑别的因素,独立于研发的变更发布。我们有个特点,我们研发是通过运维提供的变更系统,他在上面基本上不需要做什么操作,整条链就打通了,运维不用关心变更发布,只需要管好服务伸缩就好。

1.3 数据存储规范

image.png-185kB

接入层和逻辑层的服务伸缩,无需考虑数据迁移和cache命中率。

数据存储方面,单独拎一页出来是觉得这个场景是比较多人中招的,比如接入层肯定不会带什么数据的,逻辑层我希望它是不带数据的,而且我们也严格要求不带数据的。

经常出现这样的场景,他的逻辑层要自动伸缩,跑了一段时间上线了一些逻辑在上面保存了一些数据,在下面做缩容的时候是不是就中招了,会有这个问题,所以我们会定这个规范。

逻辑层是不带数据的,会有静态数据,包括用户发的消息、用户发的朋友圈,很明显应该放到存储层的。

接入层不带数据,其实历史上我们也有一次是带了数据的,在每次过年抢红包的时候,所有人都在摇的那一把,其实那个量是非常恐怖的,摇红包那个点我们做设计是每个摇红包的请求真的打倒我们接入层,不会有客户端摇五次才有一次请求上来。我们的接入层的性能保证我们能抗住这个量,但是后面的逻辑层肯定撑不了这个量,1秒钟几千万,这个时候我们会做一些很特殊的逻辑,在接入层直接带上红包数据,当然这是比较特殊的场景,我们只在过年的时候这个规范是没有执行的。

1.4 运营规范小结

image.png-88.7kB

这里说了几点,我们的目标简单来说就是服务可运维,可运维的意思就是你做扩容缩容的时候不需要做人工的操作,如果做人工的操作就是不可运维。

我们为了实现服务可运维,在变更系统里做了一些拦截,它接下来变更可能不符合我们运营规范或者之前有不符合我们运营规范的地方,我们都会拦下来,要求变更,实现我们的运维规范。

二. 云化管理

接下来说一下云,大家用云也挺多的,近几年也比较火,可能大家用得比较多的是Docker,微信这边我们没有用Docker,后面也会说到为什么没有用。

2.1 为什么上云

image.png-67.3kB

先说为什么要上云,在2013年、2014年时,我们的微服务已经到差不多5000个,其实我是近几年才知道这个叫微服务,我们之前实现方式已经是好多年都算微服务的方式。

其实最开始说微服务这个事情的时候,我记得是QQ那边海量运营的一些课程都会提到,我觉得这个思路跟微服务是完全一致的。

我们运维这边在实现了一套新服务发布的时候,基本上不会给研发有什么限制说你这个服务不要搞太多,所以整个系统搞下来那个量是比较夸张的,当然就会出现他的多个服务要在同一台机上部署,因为里有5000个微服务,一定要同物理机部署。

部署多个服务就会有资源抢占,基于这个因素,我们就上云。

2.2 哪部分上云

image.png-158.6kB

哪一块上云,刚才也说到,接入层因为要扛住比较猛的量,微信的用户也比较多,如果它有什么问题,可能接入层会雪崩。所以我们主要是独占物理机,容量足,变更也少,暂时没有上云的需求。

在逻辑层这里,之前提到5000多个微服务,所以比较混乱,变更比较多,容量也不可控,所以这块上了云。

存储层这里,也没有上云,但是有单独的容量管理和数据迁移。

2.3 基于Cgroup的云化

image.png-152.5kB

我们云的方式是直接Cgroup,Cgroup这个名字可能有些人不知道,我们用的是内核Cgroup这种机制。

在现网的时候,用类似简单的虚拟机型定制,比如1个cpu+1G内存。前期我们也有一些流量因素的考虑,后来把它给取消掉了,我们系统架构上保证的那个流量好像是不怎么会成为问题的。

这里简单列了一下虚拟机分片的方式,怎么隔的方式都有,我们隔的这么随意也带来另外一个问题,系统运转过程中会有一些类似于磁盘碎片的东西存在,好像你Windows跑了很久以后也会有磁盘碎片存在一样。这个我们也有一些比较特殊的方法来处理。

2.4 线上未启用Docker

image.png-99.3kB

这里列了一下我们没有用Docker的原因。

Docker太火了,我们差不多在2014年、2015年的时候,线上也少量上线了一轮。

我们这个svrkit框架是我们微信内部自研的一套框架,100%覆盖全网,100%什么意思,一点开源代码都没有,包括前面大家可能用得最多的nginx做接入,这个我们也是在自研的切换的,包括后面的存储,前期用了MySQL,后期也都换成自己的组件了。

现网用我们自己的框架100%覆盖了,我们的标准化和规范化都是比较好的。

可以说Docker解决的一些问题在我们这里不是问题。

2.5 私有云调度系统

基于上面的点我们自研了一套云化管理的Docker系统。这是我们私有云调度系统:

image.png-100.9kB

基于我前面提到的svrkit框架+自研,调度系统当然也要用我们自己的调度系统覆盖,目前覆盖了80%的微服务,还差一点点100%覆盖。

2.6 私有云调度系统架构

image.png-408.8kB

这是我们的架构,熟悉的人一看就知道跟业界的事情没有什么区别,中间有一些虚拟化的坑,可以认为跟大家用得没有太大区别,不细讲了。

2.7 云化管理小结

image.png-113.8kB

在云化管理这一块,我们实现的一个目标就是资源隔离,Docker服务之间不要说一个服务异常搞的第二个服务也异常。

第二是服务伸缩页面化操作,有些服务还是很庞大的,一个服务下几千上万台都可能,这种时候不希望你上机器的,在页面上点就可以了。

我们为了落实这个目标,会把部署系统,把那些没有上云的拦住,他要走旧的部署方式上线,他需要走旧的流程才能走旧的商业模式。

前面这些运营规范和云化管理,相信大家多多少少都会有自己的实现方式,也都会有自己的一些总结。后面容量这块不确定大家都是怎么改这一块的。

三. 内容管理

3.1 如何支撑业务发展

image.png-145.9kB

这是一个业务量增长的曲线,这是我们容量的曲线。

一般来说你扩了一次容就一直平在这里,有一个点你发现撑不住了,要扩容,打上去,就一直保持这个状态,跟容量曲线是不怎么匹配的。

第一个点是你这个容量低于现网的业务量的时候,这其实是容量不足的,能不能很快发现这个问题。

第二个点是处理效率,容量不足的时候把曲线打上去,扩容需要多长时间,如果是几天或者几分钟,这个效率是不一样的。

我们希望实现的一个最优容量的方式,它跟业务增长完全是匹配的方式。

这个曲线并不很难实现,只要你那个J字型够频繁,跟这个就是完全吻合的最优容量的曲线。

你发现它容量不足是分钟级的,扩容也是分钟级的,那你完全可以描出这么一套一模一样的曲线出来。

3.2 使用硬件指标评估容量

image.png-72.6kB

我们会说你怎么知道这个服务的容量不足的?一般我们第一个反应就是用硬件指标,包括CPU使用率是多少,磁盘空间多少,网卡容量、内存。这也能解决到问题,但它不能解决所有问题。

3.3 使用CPU评估容量

image.png-154kB

服务容量 = 当前峰值/经验CPU上限

这是一个使用CPU来算服务容量的方式。

这是一个简单的例子,比如你现在CPU当前峰值40%,你自己的经验觉得这个能达到80%的CPU,简单除下就是50%的容量。

3.4 硬件指标是否可靠

image.png-901.4kB

这东西靠谱吗?我这里画了两个示意图:

有些类似左边这张图是靠谱的,容量基本上和CPU保持增长的。

有些类似右边这张图窄口瓶,CPU涨到一定点的时候,容量就上不去。

3.5 真实案例

image.png-237.7kB

这是现网打流量的例子,人为把流量打上去,会发现有些服务怎么打都是在80%;有些怎么都是60%,上不去。

3.6 硬件指标的局限性

image.png-115.1kB

硬件指标我们认为有一些局限性:

确实,线上服务多了以后,做的事情不大可控。

我们觉得应该要通过压测,才能比较准确的得到容量的模型。

3.7 压测方式

image.png-158.4kB

压侧方式分两种:

环境也是分两种:

四种压测方式。

** 第一种**模拟流量在测试环境打的时候,测试团队内部对质量的一些验证,这种测试方式是测试团队负责的,我们没有太参与。

** 第二种**模拟流量打现网有点类似于全链路压测,比如淘宝在双十一经常这么干,对微信来说,我们只在过年这么干,微信过年好像跟淘宝双十一差不多,都是一个比较疯狂的状态,所以我们会在过年前用模拟的流量打一下现网,这个不是一个很常见的压测方式。

第三种真实流量往测试环境打,一般是我们要验证一些存储性能时会这么干,把线上的流量旁路打到测试环境里面,看一下这些存储性能的情况,可以在测试环境里比较好的模拟出来,不会影响到现网。

第四种真实流量打现网环境,我这里主要想说的,我们真的在现网压测,用真实的流量打现网环境是什么状况。

3.8 现网压测

image.png-94.2kB

现网压测实现起来非常简单,当你名字服务这块实现比较标准的话,都是统一的流程,就是压侧流程,不停的调其中一个服务的权重,观察它是什么后果就行了。

3.9 现网压测可能导致的异常

image.png-103.6kB

这样压有什么问题,大家都能想到,你压那个服务,什么时候停,怎么能保证不要搞出事来。我们认为这里有以下三个点:

我认为这三个问题是比较关键的。

3.10 服务的自我保护

image.png-112.6kB

你的各个服务有没有做好自我保护。我们引入了一个快速拒绝的概念,这个服务正常的时候,可能你的上线每分钟100万个请求也是能正常服务的,上游服务给你500万的时候,你只能处理100万,你能不能把其他400万个请求拒绝掉,这是我们框架实现的能力。

3.11 上游服务的重试保护

image.png-149.7kB

上游服务重试保护是怎么样的?比如你在压其中一个实例的时候,你一直加大它的权重,导致它快速拒绝返回失败了,那你有没有一个机制走到其他的实例把整个流程跑完,这也是一个比较关键的点,这个我们也是在框架里支持了。

3.12 立体化监控

image.png-112.9kB

监控体系够不够完善,包括硬件的监控,刚才提到快速拒绝的监控,还有前端跟后端这种耗时的监控,还有刚才提到的前面这种,有没有发生失败,整条线都是我们需要关注的。

可以这么说,有了服务的自我保护、上游服务的重试保护、立体化监控,我们才敢压测,如果这三个点搞不定,压测这个事情做不了。

3.13 秒级监控

image.png-185.4kB

能不能快的发现你的异常?为了这个问题,我们把分钟级的监控升级成了秒级的监控,所有的异常差不多都是10秒钟之内就能发现。

整个实现的方式大家应该都差不多,每台机都有个采集的,之前是每分钟上报一次到队列,然后再汇总,然后再入库。现在我们改了这个逻辑,6秒钟做一次采集,然后数据转化,然后做一个秒级数据的汇总。

上面还是分钟级的。

3.14 放量速率动态控制

image.png-192.9kB

这里还有一个速率的动态控制,这里比较复杂,不知道怎么解释这种情况。

左边这张图是我们比较早期压测的实现方式,它从一个点开始,可能用一个比较快速的调整它权重的方式,直到调用失败出来了,然后再回退,再继续往上压,不停往上不往下,用这种方式来接近你的容量上限。这个点大家很明显看到一个问题,运维在压测的时候其实是给自己找事,每次压测都打上来,又掉下去,打上来。失败曲线就像狗啃的一样,一直有抖来抖去的曲线。这种压测方式,运维自己都受不了。

后面我们调了一下,其实这个也跟我们服务框架提供的能力相关,我们整个服务框架会有一个入队/出队的机制,每个微服务本身都会有这样的机制。这里的队列的积压情况是比较关键的指标,我们会监控入队延迟,它出队,发现它一有积压,性能已经跟不上了,我们通过这种指标来调整压测的速率,大概实现的效果是右边这张图。前期是比较快的权重,当观察到队列已经有积压有延迟,就开始放缓,一直达到一个点,可能最后那个点是有一点点压测失败,实现这么一个效果,整个过程中可能只有几秒钟,就得到性能模型,得到压测真实的值。

3.15 现网压测效果

image.png-262.4kB

这是我们真实的线上压缩的结果。

这张图打出来的斜率是先涨得比较快,后期再慢慢增长,然后把这个压测点停掉了。

为了打出这张图的效果,我们还搞了蛮久的,可能大概一年多才达到这种现状,基本上不会给现网服务带来失败的。

3.16 容量管理小结

image.png-66.1kB

这个事情我们做完了,觉得有几方面的收益:

四. 自动调度

4.1 业务增长的自动扩容

image.png-157.4kB

解决业务增长的自动扩容,因为你的业务量在涨,其实你的用户的请求包括各种请求量都是跟着指标在涨的,你知道业务量怎么增长,知道微服务怎么增长曲线,前面的压测又知道每个实例的性能怎么样,你就能够准确知道我现在容量大概比例是在哪条线上。

我们一般让它跑在50%、60%这个区间内,66%是一个容灾的预留,我们先部署三个IDC里面,你要想挂掉两个,另外一个也不会有什么异常的话,可能就是这两个限。

我们会留出一些时间给采购机器给我们,会把一些服务的流量控制在50%这个点。

4.2 异常情况的自动扩容

image.png-170kB

还有一些异常的情况:

4.3 程序性能下降的合理性评估

image.png-317.8kB

我们差不多有些服务是2015年每天都在压,每一天他的性能是怎么样的,我们描出一条曲线出来。可能会发现有一些时间点性能下降比较远,比如这里的例子是他发了个大版本,特性里面增加了一些处理逻辑,所以性能下降比较明显。这个事情可能过了一两个月以后,有些同事出来解决fix它,这种性能监控我认为在前面的容量管理和智能交互这一块的副产品,这个副产品我们用得还比较多的,可以准确知道整个微服务性能变化怎么样。

4.4 性能管理闭环

image.png-110.2kB

能不能不要让它出现这种新的下降的点,我们每天都在压,能不能再快一点,直接在它上线的时候直接拦住。比如说开发同学灰度上了一个台机,我们马上压测它灰度上线的这台的这个机器,看它的性能怎么样,如果发现它的性能下降,就把他拉住。

4.5 几种业务形态

image.png-709.2kB

这是我们现网的一些业务形态,可能比较多的就是最上面这种图,它在晚上9点到10点迎来它的最高峰。

中间这种图一般跟工作相关的如微信,工作时间段用得比较多的。

还有一种是最底下这种,比较典型的例子是微信活动,微信活动好像是晚上22点的时候会来一步。还有一些比较古老的业务,漂流瓶,用得脑残粉还挺多的,他们会守着0点的时候。

4.6 削峰填谷

image.png-397.4kB

我们对这些业务曲线希望做什么?

第一,峰那么高,我们所有的设备都是为了应付最高的那个峰,这个峰能不能做点特殊处理,不给它们危险设备。

还有第二个,晚上零点以后,这么低的业务量,设备挺浪费的。

我们希望有一个削峰填谷的作用,原理还是很简单,就是把你的有些服务跟另外一些服务的峰值错开。有些服务高峰期过了,把它的资源放弃出来,至于谁去用它不管。

4.7 在线业务削峰

image.png-146kB

4.8 离线计算填谷

image.png-143kB

离线计算,凌晨那段时间确实都很闲。这个时候比较适合离线计算来调度,微信群之前离线计算的东西比较少,主要是语音输入等一些人工智能方面的东西。最近可能有一些看一看、搜一搜新功能,他们用的离线计算的调度还挺多的。

资源占用方面,这几个场所的配置基本上是Cgroup控制得比较严格一些。

然后把离线任务的优先级调一下,用离线任务来把我们低峰的谷填平了。

4.9 自动调度小结

image.png-78.2kB

这在自动调度这块是我们实现的一个目标:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注