微信业务量增加的时候,其实咱们比较关心的是效率。前期可能两三个月就涨了1倍的量,咱们怎么可以保证咱们的运营效率是跟得上的?后期可能主要是关心成本。咱们在2014年之后增加有点放缓,因此主要的精力会在成本这个方面。前端
分为四块来讲:nginx
运营规范
云化管理
容量管理后端
自动调度微信
运营规范架构
配置文件规范框架
先来看配置文件规范,咱们前期花了比较多的精力。可能整个系统设计比较复杂,最开始都会有一些配置管理工程师专门来处理,后期咱们把这块搞得比较规范了。运维
配置文件规范分为下面几项:微服务
目录结构标准
这就是一个服务部署上线的时候怎么定义它的目录结构,你们应该先作好这些目录结构标准的定义。性能
跨服务的相同配置项管理
为何提这一点?可能有些配置项你会在这个服务里须要这几个配置项,在另外一个服务里也须要这几个配置项。若是更改这个配置项的时候,你是否是把服务A发一遍,服务B也发一遍?咱们有一套机制,每台机每一个目录下都会有一个全局共用的配置项,咱们会经过一些自动化的灰度的方式来控制这里的发布,这一块是单独拎出来的。测试
同一服务内不一样实例的差别配置项管理
不肯定你们运营时会不会碰到相似的问题,就算你用Docker了你镜像管理挺好的。你部署个实例出来,可能大家的业务就须要你把实例1上作一些调整,固然你也能够用脚原本管理。可是咱们以为这是比较复杂的状态,咱们会把这些差别性所有给它统一抽取出来,尽可能作到全部的环境下它的配置文件的MD5都是一致的。
开发/测试/现网的差别配置项管理
前期也会有这个问题,开发环境咱们通常无论,测试环境也是运维来负责管理,现网固然是运维管理的。基本上测试和现网的差别只有路由的差别,其余的配置项咱们都保证它是彻底一致的。作这么一个要求,大概实现的效果是无论你经过什么手段扩容,咱们直接一个镜像打过去或者直接一个包拷过去就能够了,不会再有后续的脚原本改动它。
同一服务下同一版本的多个实例,在全部环境下配置 文件的md5都严格一致。
名字服务规范
名字服务这块比较重要,分三层:
服务伸缩是运维工程,独立于研发的变动发布。
接入层和逻辑层,都是相似的实现,咱们内部根据咱们的业务特性作了一些业务开发。
存储层跟QQ有点不同,QQ好像是逻辑层和存储层都是用同一个名字服务实现,咱们在存储层这里尚未作这方面的配置。
咱们如今存储层跟逻辑层隔得比较开,在涉及到数据的方面,咱们差很少能够认为是运维可以配置的方式,可是又不彻底是可以配置,用那些辅助脚原本配置。
服务伸缩是运维工程,咱们不但愿在服务伸缩时还考虑别的因素,独立于研发的变动发布。咱们有个特色,咱们研发是经过运维提供的变动系统,他在上面基本上不须要作什么操做,整条链就打通了,运维不用关心变动发布,只须要管好服务伸缩就好。
接入层和逻辑层的服务伸缩,无需考虑数据迁移和cache命中率。
数据存储方面,单独拎一页出来是以为这个场景是比较多人中招的,好比接入层确定不会带什么数据的,逻辑层我但愿它是不带数据的,并且咱们也严格要求不带数据的。
常常出现这样的场景,他的逻辑层要自动伸缩,跑了一段时间上线了一些逻辑在上面保存了一些数据,在下面作缩容的时候是否是就中招了,会有这个问题,因此咱们会定这个规范。
逻辑层是不带数据的,会有静态数据,包括用户发的消息、用户发的朋友圈,很明显应该放到存储层的。
接入层不带数据,其实历史上咱们也有一次是带了数据的,在每次过年抢红包的时候,全部人都在摇的那一把,其实那个量是很是恐怖的,摇红包那个点咱们作设计是每一个摇红包的请求真的打倒咱们接入层,不会有客户端摇五次才有一次请求上来。咱们的接入层的性能保证咱们能抗住这个量,可是后面的逻辑层确定撑不了这个量,1秒钟几千万,这个时候咱们会作一些很特殊的逻辑,在接入层直接带上红包数据,固然这是比较特殊的场景,咱们只在过年的时候这个规范是没有执行的。
运营规范小结
这里说了几点,咱们的目标简单来讲就是服务可运维,可运维的意思就是你作扩容缩容的时候不须要作人工的操做,若是作人工的操做就是不可运维。
咱们为了实现服务可运维,在变动系统里作了一些拦截,它接下来变动可能不符合咱们运营规范或者以前有不符合咱们运营规范的地方,咱们都会拦下来,要求变动,实现咱们的运维规范。
云化管理
接下来讲一下云,你们用云也挺多的,近几年也比较火,可能你们用得比较多的是Docker,微信这边咱们没有用Docker,后面也会说到为何没有用。
为何上云
先说为何要上云,在2013年、2014年时,咱们的微服务已经到差很少5000个,其实我是近几年才知道这个叫微服务,咱们以前实现方式已是好多年都算微服务的方式。
其实最开始说微服务这个事情的时候,我记得是QQ那边海量运营的一些课程都会提到,我以为这个思路跟微服务是彻底一致的。
咱们运维这边在实现了一套新服务发布的时候,基本上不会给研发有什么限制说你这个服务不要搞太多,因此整个系统搞下来那个量是比较夸张的,固然就会出现他的多个服务要在同一台机上部署,由于里有5000个微服务,必定要同物理机部署。
部署多个服务就会有资源抢占,基于这个因素,咱们就上云。
哪部分上云
哪一块上云,刚才也说到,接入层由于要扛住比较猛的量,微信的用户也比较多,若是它有什么问题,可能接入层会雪崩。因此咱们主要是独占物理机,容量足,变动也少,暂时没有上云的需求。
在逻辑层这里,以前提到5000多个微服务,因此比较混乱,变动比较多,容量也不可控,因此这块上了云。
存储层这里,也没有上云,可是有单独的容量管理和数据迁移。
基于Cgroup的云化
咱们云的方式是直接Cgroup,Cgroup这个名字可能有些人不知道,咱们用的是内核Cgroup这种机制。
在现网的时候,用相似简单的虚拟机型定制,好比1个cpu+1G内存。前期咱们也有一些流量因素的考虑,后来把它给取消掉了,咱们系统架构上保证的那个流量好像是不怎么会成为问题的。
这里简单列了一下虚拟机分片的方式,怎么隔的方式都有,咱们隔的这么随意也带来另一个问题,系统运转过程当中会有一些相似于磁盘碎片的东西存在,好像你Windows跑了好久之后也会有磁盘碎片存在同样。这个咱们也有一些比较特殊的方法来处理。
线上未启用Docker
这里列了一下咱们没有用Docker的缘由。
Docker太火了,咱们差很少在2014年、2015年的时候,线上也少许上线了一轮。
咱们这个svrkit框架是咱们微信内部自研的一套框架,100%覆盖全网,100%什么意思,一点开源代码都没有,包括前面你们可能用得最多的nginx作接入,这个咱们也是在自研的切换的,包括后面的存储,前期用了MySQL,后期也都换成本身的组件了。
现网用咱们本身的框架100%覆盖了,咱们的标准化和规范化都是比较好的。
能够说Docker解决的一些问题在咱们这里不是问题。
对Docker的需求不是很强烈
框架自己咱们用了不少IPC交互
这些东西其实在Docker里都作了很严格的规范,若是咱们用Docker,咱们可能会把这些Docker里的各类机制破坏掉。若是是这种状况,还不如不用Docker。
对Docker这种接入方式的实现仍是有顾虑
早一两年有人跟我讨论比较多,Docker主进程起来的时候,可能你因为要更新Docker自己,会致使你的服务重启。
好像近期已经解决这个问题,这个在早期来看咱们认为是一个比较严重的问题,我不但愿说由于Docker自己的变动,对线上的服务有任何影响。
私有云调度系统
基于上面的点咱们自研了一套云化管理的Docker系统。这是咱们私有云调度系统:
基于我前面提到的svrkit框架+自研,调度系统固然也要用咱们本身的调度系统覆盖,目前覆盖了80%的微服务,还差一点点100%覆盖。
私有云调度系统架构
这是咱们的架构,熟悉的人一看就知道跟业界的事情没有什么区别,中间有一些虚拟化的坑,能够认为跟你们用得没有太大区别,不细讲了。
云化管理小结
在云化管理这一块,咱们实现的一个目标就是资源隔离,Docker服务之间不要由于一个服务异常搞的第二个服务也异常。
第二是服务伸缩页面化操做,有些服务仍是很庞大的,一个服务下几千上万台均可能,这种时候不但愿你上机器的,在页面上点就能够了。
咱们为了落实这个目标,会把部署系统,把那些没有上云的拦住,他要走旧的部署方式上线,他须要走旧的流程才能走旧的商业模式。
前面这些运营规范和云化管理,相信你们多多少少都会有本身的实现方式,也都会有本身的一些总结。后面容量这块不肯定你们都是怎么改这一块的。
容量管理
如何支撑业务发展
这是一个业务量增加的曲线,这是咱们容量的曲线。
通常来讲你扩了一次容就一直平衡在这里,有一个点你发现撑不住了,要扩容,扩上去,就一直保持这个状态,跟容量曲线是不怎么匹配的。
第一个点是你这个容量低于现网的业务量的时候,这实际上是容量不足的,能不能很快发现这个问题。
第二个点是处理效率,容量不足的时候把曲线打上去,扩容须要多长时间,若是是几天或者几分钟,这个效率是不同的。
咱们但愿实现的一个最优容量的方式,它跟业务增加彻底是匹配的方式。
这个曲线并不很难实现,只要扩容够频繁,跟这个就是彻底吻合的最优容量的曲线。
你发现它容量不足是分钟级的,扩容也是分钟级的,那你彻底能够描出这么一套如出一辙的曲线出来。
使用硬件指标评估容量
咱们会说你怎么知道这个服务的容量不足的?通常咱们第一个反应就是用硬件指标,包括CPU使用率是多少,磁盘空间多少,网卡容量、内存。这也能解决到问题,但它不能解决全部问题。
使用CPU评估容量
服务容量 = 当前峰值/经验CPU上限
这是一个使用CPU来算服务容量的方式。
这是一个简单的例子,好比你如今CPU当前峰值40%,你本身的经验以为这个能达到80%的CPU,简单除下就是50%的容量。
硬件指标是否可靠
这东西靠谱吗?我这里画了两个示意图:
有些相似左边这张图是靠谱的,容量基本上和CPU保持增加的。
有些相似右边这张图窄口瓶,CPU涨到必定点的时候,容量就上不去。
真实案例
这是现网打流量的例子,人为把流量打上去,会发现有些服务怎么打都是在80%;有些怎么都是60%,上不去。
硬件指标的局限性
硬件指标咱们认为有一些局限性:
确实,线上服务多了之后,作的事情不大可控。
咱们以为应该要经过压测,才能比较准确的获得容量的模型。
压测方式
压侧方式分两种:
环境也是分两种:
四种压测方式
第一种模拟流量在测试环境打的时候,测试团队内部对质量的一些验证,这种测试方式是测试团队负责的,咱们没有太参与。
第二种模拟流量打现网有点相似于全链路压测,好比淘宝在双十一常常这么干,对微信来讲,咱们只在过年这么干,微信过年好像跟淘宝双十一差很少,都是一个比较疯狂的状态,因此咱们会在过年前用模拟的流量打一下现网,这个不是一个很常见的压测方式。
第三种真实流量往测试环境打,通常是咱们要验证一些存储性能时会这么干,把线上的流量旁路打到测试环境里面,看一下这些存储性能的状况,能够在测试环境里比较好的模拟出来,不会影响到现网。
第四种真实流量打现网环境,我这里主要想说的,咱们真的在现网压测,用真实的流量打现网环境是什么情况。
现网压测
现网压测实现起来很是简单,当你名字服务这块实现比较标准的话,都是统一的流程,就是压侧流程,不停的调其中一个服务的权重,观察它是什么后果就好了。
现网压测可能致使的异常
这样压有什么问题,你们都能想到,你压那个服务,何时停,怎么能保证不要搞出事来。咱们认为这里有如下三个点:
我认为这三个问题是比较关键的。
服务的自我保护
你的各个服务有没有作好自我保护。咱们引入了一个快速拒绝的概念,这个服务正常的时候,可能你的上线每分钟100万个请求也是能正常服务的,上游服务给你500万的时候,你只能处理100万,你能不能把其余400万个请求拒绝掉,这是咱们框架实现的能力
上游服务的重试保护
上游服务重试保护是怎么样的?好比你在压其中一个实例的时候,你一直加大它的权重,致使它快速拒绝返回失败了,那你有没有一个机制走到其余的实例把整个流程跑完,这也是一个比较关键的点,这个咱们也是在框架里支持了。
立体化监控
监控体系够不够完善,包括硬件的监控,刚才提到快速拒绝的监控,还有前端跟后端这种耗时的监控,还有刚才提到的前面这种,有没有发生失败,整条线都是咱们须要关注的。
能够这么说,有了服务的自我保护、上游服务的重试保护、立体化监控,咱们才敢压测,若是这三个点搞不定,压测这个事情作不了。
秒级监控
能不能快的发现你的异常?为了这个问题,咱们把分钟级的监控升级成了秒级的监控,全部的异常差很少都是10秒钟以内就能发现。
整个实现的方式你们应该都差很少,每台机都有个采集的,以前是每分钟上报一次到队列,而后再汇总,而后再入库。如今咱们改了这个逻辑,6秒钟作一次采集,而后数据转化,而后作一个秒级数据的汇总。
上面仍是分钟级的。
放量速率动态控制
这里还有一个速率的动态控制,这里比较复杂,不知道怎么解释这种状况。
左边这张图是咱们比较早期压测的实现方式,它从一个点开始,可能用一个比较快速的调整它权重的方式,直到调用失败出来了,而后再回退,再继续往上压,不停往上不往下,用这种方式来接近你的容量上限。这个点你们很明显看到一个问题,运维在压测的时候实际上是给本身找事,每次压测都打上来,又掉下去,打上来。失败曲线就像狗啃的同样,一直有抖来抖去的曲线。这种压测方式,运维本身都受不了。
后面咱们调了一下,其实这个也跟咱们服务框架提供的能力相关,咱们整个服务框架会有一个入队/出队的机制,每一个微服务自己都会有这样的机制。这里的队列的积压状况是比较关键的指标,咱们会监控入队延迟,它出队,发现它一有积压,性能已经跟不上了,咱们经过这种指标来调整压测的速率,大概实现的效果是右边这张图。前期是比较快的权重,当观察到队列已经有积压有延迟,就开始放缓,一直达到一个点,可能最后那个点是有一点点压测失败,实现这么一个效果,整个过程当中可能只有几秒钟,就获得性能模型,获得压测真实的值。
现网压测效果
这是咱们真实的线上压缩的结果。
这张图打出来的斜率是先涨得比较快,后期再慢慢增加,而后把这个压测点停掉了。
为了打出这张图的效果,咱们还搞了蛮久的,可能大概一年多才达到这种现状,基本上不会给现网服务带来失败的。
容量管理小结
这个事情咱们作完了,以为有几方面的收益:
服务的资源需求可准确量化
刚才提到几百微服务,每一个是怎么算出来的。
怎么知道你这个微服务适合于哪一种机型?有些服务根据咱们压测会发现它有些场景跟别人不同,咱们只要把自动化压测的方式实现了,每一个模型试一下,压出来你知道它最优的机型是怎么样的。
自动调度
业务增加的自动扩容
解决业务增加的自动扩容,由于你的业务量在涨,其实你的用户的请求包括各类请求量都是跟着指标在涨的,你知道业务量怎么增加,知道微服务怎么增加曲线,前面的压测又知道每一个实例的性能怎么样,你就可以准确知道我如今容量大概比例是在哪条线上。
咱们通常让它跑在50%、60%这个区间内,66%是一个容灾的预留,咱们先部署三个IDC里面,你要想挂掉两个,另一个也不会有什么异常的话,可能就是这两个限。
咱们会留出一些时间给采购机器给咱们,会把一些服务的流量控制在50%这个点。
异常状况的自动扩容
还有一些异常的状况:
这种某些产品搞活动没有通知咱们,咱们会用一些粗暴的方式来解决,包括说CPU,咱们会给它定一个点,当你的CPU冲过这个点的时候,咱们会自动发起扩容。
你业务没有太大有变化,但你程序变了,这其实也会致使容量不ok。这个点咱们是可以监测到这种状况的,就看咱们压测的频率有多频繁,若是你天天都压测,你把压测的曲线描出来。
程序性能降低的合理性评估
咱们差很少有些服务是2015年天天都在压,每一天他的性能是怎么样的,咱们描出一条曲线出来。可能会发现有一些时间点性能降低比较远,好比这里的例子是他发了个大版本,特性里面增长了一些处理逻辑,因此性能降低比较明显。这个事情可能过了一两个月之后,有些同事出来解决fix它,这种性能监控我认为在前面的容量管理和智能交互这一块的副产品,这个副产品咱们用得还比较多的,能够准确知道整个微服务性能变化怎么样。
性能管理闭环
能不能不要让它出现这种新的降低的点,咱们天天都在压,能不能再快一点,直接在它上线的时候直接拦住。好比说开发同窗灰度上了一个台机,咱们立刻压测它灰度上线的这台的这个机器,看它的性能怎么样,若是发现它的性能降低,就把他拉住。
几种业务形态
这是咱们现网的一些业务形态,可能比较多的就是最上面这种图,它在晚上9点到10点迎来它的最高峰。
中间这种图通常跟工做相关的如微信,工做时间段用得比较多的。
还有一种是最底下这种,比较典型的例子是微信活动,微信活动好像是晚上22点的时候会来一步。还有一些比较古老的业务,漂流瓶,用得脑残粉还挺多的,他们会守着0点的时候。
削峰填谷
咱们对这些业务曲线但愿作什么?
第一,峰那么高,咱们全部的设备都是为了应付最高的那个峰,这个峰能不能作点特殊处理,不给它们危险设备。
第二,晚上零点之后,这么低的业务量,设备挺浪费的。
咱们但愿有一个削峰填谷的做用,原理仍是很简单,就是把你的有些服务跟另一些服务的峰值错开。有些服务高峰期过了,把它的资源放弃出来,至于谁去用它无论。
在线业务削峰
离线计算填谷
cpu.shares + memory.limit_in_bytes + blkio
离线计算,凌晨那段时间确实都很闲。这个时候比较适合离线计算来调度,微信群以前离线计算的东西比较少,主要是语音输入等一些人工智能方面的东西。最近可能有一些看一看、搜一搜新功能,他们用的离线计算的调度还挺多的。
资源占用方面,这几个场所的配置基本上是Cgroup控制得比较严格一些。
而后把离线任务的优先级调一下,用离线任务来把咱们低峰的谷填平了。
自动调度小结
这在自动调度这块是咱们实现的一个目标: