腾讯QQ日请求12亿的运营平台到底有多diao(三声)?

您可识别下方二维码收听昨晚的直播内容,解放您的双眼:


作者简介:

徐汉彬
腾讯 SNG增值产品部高级工程师

QQ会员体系合作线技术团队负责人。曾就职于阿里巴巴、小满科技。QQ会员活动运营平台的初始开发,在五年的时间里,将该平台从日请求百万级升至十亿量级(日请求4-12亿),成为腾讯流量支撑规模最大的Web系统之一,负责该平台的架构设计和研发建设,在Web系统架构方面拥有比较丰富的实践和积累。

前言

作者目前在SNG增值产品部工作,主要负责QQ会员会员特权和AMS系统的相关工作。作者之前有AMS系统相关的文章《日请求从百万到八亿的技术历程》

本文的内容主要分为三个部分:

第一个是业务系统链路的梳理和流量评估;

第二是关于AMS系统高可用架构设计实践;

第三是QQ春节红包当天实践经验和总结;

1、业务系统链路的梳理和流量评估

1.1 什么是运营活动

AMS是一个活动运营平台,什么是活动?

活动就上图体现的四个页面,这些都叫活动。这时候可能有同学说,“楼主,我读书多你不用骗我,这上面东西很简单,这里会不会一点技术含量都没有?”

是的,如果本文的东西只是这上面几个页面的话,肯定是没有什么技术含量。但是如果将他们放到比较大的流量规模下,15万每秒,就会变成具有挑战的问题

1.2 AMS系统介绍

简单介绍一下 AMS,其实是QQ会员的活动运营平台,这个平台的日请求量大概是4到12亿,背后涉及的存储和服务超过了120个,高峰期的请求量是15万每秒。

这个系统也支撑了腾讯公司相关的业务,我们连续两年参加了QQ春节红包的活动。在今年除夕夜晚上,你可能正在跟家里人吃着饭看着电视,而这时候我则在公司值班,一直值班到大年初一的凌晨三四点,所以做这个系统也不那么容易。

1.3 QQ春节红包活动面临的挑战

关于这个活动会面临哪些挑战呢?主要有三个方面的挑战。

  • 第一,流量规模到底有多大?我们怎么预估?流量是10万20万还是多少?怎么预估流量规模,这是个难题。

  • 第二,假设你把流量规模已经预估出来,对于一个比较复杂的系统,里面有存在大量的系统与系统之间的调用,整个会有很复杂的系统架构链,这个架构链哪怕你评估出流量规模,但是要想对架构链进行合适的扩容也是难点,有时候我们会无从下手。

  • 第三,哪怕前面两个问题都解决了,我怎样保证活动的当天不出问题呢?今天的分享就围绕着这三个问题为核心一步一步展开,也跟大家做一个探讨。

1.4 业务系统的架构梳理

第一个问题是关于如何评估流量链路的问题,第一步就需要把我们的系统架构给画出来,我现在画的是简化图,先将用户跟每个子系统的关系,但这是业务层面的,具体到 server 和存储。

上面这个图主要分为两个部分,一部分是请求领取页面,后面是比较复杂的动态系统。画出这个东西是为了下面一步,就是以具体功能的节点,把用户涉及的所有链路一个一个梳理并且画出来。

比如以查询游戏角色的信息相关的东西为链路,用户首先是领到一个红包,点击领取红包到领取页,在页面可能会是点击一个按钮,然后发送请求,请求先到我们的 STGW(也就是反向代理),然后到 WEB server,再到 Cmem,再到 IDIP 以及背后的庞大的链路。

通过这种方式可以把每个功能点进行拆解和梳理,当我们得到这个图以后,如果只扩容 web server,不扩容后面的每个链路每个环节,扩容是不成立的。

1.5 业务功能链路拆解

有一个观点是只要有钱购买足够的机器,可以把对机器的方式对接下来,但是这个观点是不准确的。如果不能把每个架构做充分梳理和扩容的话,涉及到状态有关的服务是无法进行扩容的。

1.6 活动流量规模预估

怎么评估系统在那天的真实流量规模呢?

第一点就是推广量,你的流量怎么来,有些流量是我给 web 上广告,有些是通过 APP 流量数,这里可以得到数量,就是流量来源,然后拿到每个环节的转化率,一百个人看到这个广告,有多少人会点?

假设是20%,每个环节的转化率怎么来?一个是经验,你以前在这边上流量广告的转换率是多少。如果没有各个环节转化率的数据可以通过演习,你的活动当天可能是超大规模的,但是你可以先一部分灰度,把流量先转出来。

一百个用户有二十个人会点击领取页面,领取页面一个页面涉及到了单UV的概念,一个用户到页面可能会发起三四个静态资源请求,同时还会发出三到四个的动态相关资源的请求,这里面就要把产生的行为形成一个倍数,再把评估出来的容量估值为3倍。

以一个例子来展示:假设有一个用户领到的游戏红包是一百个人每秒的,但是这一百人当中只有60人点击进来,点击页面的人又只有30个人是真的会去点领取按钮,就用链路算出了UV值,到这个位置是需要做转换的,因为单UV的总数,可能是四个请求,假设是四个,那应该是120每秒,这120每秒意味着背后所有链路必须都能支撑120每秒,所以整个后面的环节都应该是120每秒。

通过前面的几个从推广曝光的数量,最后推算出预估值的 QBS 压力是多少。根据多年的扩容公式,估值为3倍是比较合理的,我们需要把几个对应的环节180乘以3倍也就是360的扩容。

1.7 AMS系统扩容评估

同样的方式,我们在流量层面也进行了相关扩容方面的探测和预估,但在真实场景中梳理业务需要多少流量呢?

需要9.6万每秒,差不多是10万每秒。连数字都知道了,不就是把每个环节扩容到10万每秒,问题就解决了?听起来是这样,但是大家都知道,理想是美好的,现实往往残酷,真的每个系统都能扩容到10万每秒吗?

我们遇到了一些难题,发现在整个链路中,像 web server,很轻松可以到14万每秒,但是有些地方是没办法的,包含第三方不可控的,假设我跟外部公司有通讯结合,或者跨了部门或跨了BG,有些系统就是难以扩容的,这时候我们在扩容上就遇到了难题。

比如像银行发账或者对账的接口,你说今天搞活动要扩容20倍,这个是不大科学的。我们就会遇到数量评估出来了,扩容却遇到问题,那怎么办呢?

那就是第二个话题,既然预估了数目又没法扩容,就涉及到高可用架构设计实践。

2、AMS高可用架构设计实践

2.1 基于春节红包活动链路的架构改造

怎么从架构层面解决问题,从直观的思路一般是分为三个方面。

  • 第一是异步化
    如果遇到了真的没法扩容的接口或者外公司不可控的,对方也不可能配合你来扩容的接口,只能是异步化,就是我的生产端可以快速生产,但是通过生产的方式使得接口支持10万每秒,但是消费那边就用异步接口让它慢慢消费。

  • 第二是缓存模式
    就是所谓的空间换时间,今年就遇到查这个用户是不是王者荣耀的用户,那边是来不及做好几万每秒的查询支持,那怎么办?说出来比较笨,就是把一两个亿的王者荣耀的名单打到内存缓存里,这样有用户来,我判断就不再走游戏接口,而是查我们的系统。

  • 第三是服务降级
    适应于对你的主逻辑不相影响的模块,比如实时上报,反正这种任务不是重要的,是不是可以放弃呢?或者是逻辑上进行的放弃。没有办法进行10万每秒的链路我们进行了改变,我们进行扩容,有些没法支持又非必要的进行跳过。整个链路从原来的方式拆成两条,上面的链路是可以做到支撑10万每秒,下面是不行的,但是通过这种方式使得链路能够继续往前走。我是从可用性的架构方面来解决有些环节和东西没办法扩容的问题。

2.2 扩容评估的主要要素

接下来就遇到扩容评估的相关要素,这些要素不只是上面几个点,你要细分的话有好几个细的点,但是主要评估的点是链路的 QPS,还有一些存储,包括磁盘大小、内存大小是否足够,以及带宽,带宽问题静态文件和动态的请求都是需要合适计算一下的。

这里面另外一点就是静态资源怎么解决,其实一个用户在进入页面,静态请求量是很大的,如果进入到一个页面,同时拉起好几个图片,它的拉取是很大的,虽然UV是两三万QPS,但是往往要乘以七八个甚至更多的倍数。

所以这种情况下这种流量,哪怕你用的是部署CDN,就是地理式存储,这种对服务都是有压力的,尤其是对带宽,有些带宽可能由于不足而导致请求响应更加缓慢。

那我们怎么解决?解决方案是用离线包的机制,我们会先把静态资源都准备好,当你的手机 QQ 在 WIFI 情况下会主动提前把春节红包要用到的图片给提前拉下来,放到你的内置浏览器。

等到真正参加活动的时候,静态文件几乎都是用你本地的,相当于你根本没有发起网络请求。也有一小部分用户从来没有在 WIFI 情况下触发拉取逻辑,但是这种用户是少数,所以绝大部分都是通过本地拉取的方式。

2.3 高可用架构建设的关键要点

现在每个环节的流量知道怎么做了,也把扩容完成了,但是完成扩容只是理论上没有问题,要想真正保证他们没有问题,还需要关注挺多点,这里面有几个要点。

  • 过载保护
    第一个要点是过载保护,不管流量到了真实的那天究竟有多大,有一个是保证系统不能挂掉,挂掉就是最大的失误,我可以容忍拒绝一部分请求,但是不能容忍系统无法提供服务。

  • 柔性可用
    第二是柔性可用,更多是跟业务侧紧密联系的,我在这个活动有一个逻辑,判断他是新用户,给他一个好一点的奖励包,老用户给普通礼包,这种逻辑在里面就可以做柔性可用,假设这个接口挂了,判断不出了,干脆全部把他当新用户用,这里面要包括业务和产品来做,把出问题的接口兼容起来。

  • 容灾建设
    还有容灾建设,分为两个部分,一部分是业务主干逻辑上的容灾,另一部分是指天灾人祸式的容灾,在部署层面的就是轻重问题,把轻重做隔离。

  • 监控体系 && 数据对账
    最后两点是最容易被忽略的,就是监控体系和数据对账。

2.4 过载保护

首先是过载保护,每个环节层层建立控制开关和流量控制。

  • 推广层
    第一个是推广层,如果系统出问题了,本来是8万每秒的广告就卡掉一半,实在不行就停了,让系统有喘息时间。这个开关往往到了真的没办法的情况下,才是建议用的。

  • 前端层
    第二个流量保护是有意识的将用户请求延长,本来你一点击就请求后台server,点击以后我给它随机等待两秒的时间,或者两分之内不能请求,这种功能对于错峰是很有帮助的,如果不进行用户等待时间,尖峰是很尖的。

  • CGI层
    还有一层是CGI层的保护,当他处理不过来可以过滤一部分请求,第二是可以做流量控制,保护后端接口。

  • 后端服务层
    后端外部第三方的接口QPS就是一千每秒,给两千的话肯定就压跨了,你不如做一个控制。

所以这相当于是层层开关,全部准备就绪,活动当天随时随地开启使用。这一句的结论是部分不可用,至少比彻底不可用强

2.5 轻重分离

关于轻重分离,核心点就像发货请求,也就是核心请求,不希望被任何其他集群所影响到。轻重的对比在具体业务场景里面。

比如查询用户的XX信息,这东西是比较轻的,哪怕查询失败或者有误了,查询页面或者重试一下,对用户是不会造成损失的,这种请求是要用专项资源保证的。

这是粗略的架构图,但是我们的部署是这样的,进行拆开,不会影响到背后发货的流程。

2.6 柔性可用

柔性可用关键是随时随地准备放弃一些非关键的路径,比如说上报或者不重要的操作,当然还包括一些业务层面的。在这方面的实现一般有两个方面的方法。

  • 第一种是设置一个超短耗时时间,比如平时只要五六毫秒就可以完成请求,这时候我设置二十毫秒,哪怕你连接不上或者发包失败,我最多只能你20毫秒,这是我们常用的方式,对于非关键路径不挂是好事,继续为我们提供服务,挂掉了就忽略它。

  • 第二种做法是 UDP,日志用得比较多,包括QQ钱包的卡也是走这个,UDP 更直白,我把包扔给你,也不等你的回包,这个包你挂掉了我也不管,通过这些做柔性开关,使得逻辑能够按照业务预期继续往下走。我们正常先查白名单,然后经过结果做业务逻辑,如果挂了直接跳过,这是我们的操作。

2.7 容灾建设:关键路径容灾

容灾的建设分为两块

  • 日常灾备
    我刚才提到异步消息队列的服务,要加很多的假设,每个核心服务挂了怎么办,如果挂掉如何有另外的机制保障呢?如果挂掉的话,我们的做法是本地磁盘,把队列以本地磁盘的方式写下来,后面可以通过这个磁盘日志补发。

    日志本身是很重要的,日志是要冗余,因为它也可能会挂,所以我们冗余了三个服务,一个磁盘 server 的服务,一个 kafka,还有公司自研的罗盘数据中心,任何一份数据出问题,可以拿这三个过来做核对。

    消息队列常规模式是存在内存里面的,如果服务突然间被扩掉了,内存就会丢掉,所以我们的做法是每个请求很早就落地到磁盘里,确保挂掉了重启以后继续往下走。

  • 天灾型灾备
    另外的容灾建设就是天灾型,什么机房突然停电,网络故障,更多的是通过跟运维同学的紧密配合,进行相关的部署,这些部署是跨地方部署,跨网关部署,通过这些避免偶发事件影响服务。

    前面也讲到了很多的预案,这些都要做成一键开关,如果大家参与过活动,真到那天真的没办法好好写代码,改代码,往往当天是非常紧张,很多事情做的,所以你的所有预案不能只停留在把它写出来,大概怎么操作。而是要全部变成一键开关,某个地方一致性,非常简便的变成手册,遇到A情况就是A预案,B情况就B预案,每个情况点一个按钮集成简单操作就开起来,只有这样大家才有反应时间。

2.8 监控与对账

首先监控是多维度的,比如说前端的返回码的成功率,流量的波动、礼包的发货量,分成不同的维度去监控整体数量,包括消息队列的堆积情况,每个环节的消耗情况,都要按不同维度监控起来,因为往往一个流量达到从来没有遇过的流量时,可能就不正常了,一到这个流量可能就看不见了,如果只有一个监控维度,它挂了就不知道处于什么状态。

我们用什么预案,这还涉及到决策,要基于当前有充分数据,有当前系统有充分了解情况下才能做出正确的决策,如果没有足够多的监控数据来辅助做预案启动还是不启动的话,相当于抓瞎,那是非常危险的。

所以监控是比较多同学容易忽略的,怎么样让数据汇总在一起,容易的看,根据数据做预案决策。另外就是自动对账和补发脚本,尽可能早的源头记录相关数据,在最终到账的再记录,因为这中间经历了很多链路,是否有个链路考虑不全,导致部分用户就发失败了。

要知道我们的系统平时流量下很正常,但是极端的时候可能有意想不到的场景,甚至连日志都来不及打出来,这时候对账就很重要了,甚至包括一些很极端的你的信用出现重大问题的,一些关键模块挂掉了,影响了五六分钟,这五六分钟的数据仍然可以通过对账脚本进行补发,所以对账也是非常重要的一环,他们相对来说也是容易被大家所忽略的一环。

2.9 运维体系支撑平台-织云系统

前面讲了很多管理、扩容、部署,这些东西都是依托在SNG由运维同学提供的强大系统,我们通过很多的工具,通过运维的指示体系,运维同学提供了在标准化、智能化非常高的平台,这个平台下能够使得我前面所讲的部署,什么跨机房、快速部署、扩容的流程得以快速和迅速实施,并且在实施过程中使得系统能够很顺利的跑下来,这是那天做这些活动的基础。

3、QQ春节红包活动的实战经验和总结

3.1实战状况

业务链路架构梳理完了,我们还改了很多东西,使得架构理论上扩容到可以支撑的量级,这里有个问题。活动当天到底有没有出问题呢?认为我的系统出问题的举手,看来大家对我的系统还是非常没有信心的。我前面做了这么多工作,你们就这样对我吗?当然有出问题,怎么可能不出问题?不出问题还是不正常的。

我们出了几个问题,第一个是流量超预期,原本评估是9.6万每秒,是为了省机器,扩容到14万每秒,但是均值达到12.6万每秒,峰值达到20万每秒,机器撑不住了。

实时上报 server 挂掉了,存储服务带宽跑满了,消息队列堆积非常严重,最高时候堆积达到了1200万,1200万请求进去以后,发货特别慢,问题很多。真的到了那天晚上不出问题是不正常的,你找一个大型活动不出问题的案例给我分享一下,我也想好好学习。

系统的状况是怎么样的呢?首先 web server 是高负载了,其中一个存储的服务带宽跑满了,导致请求都出不来,实时上报挂掉了,数据堆积非常严重,大家说我们慌不慌?这系统简直面目全非了,觉得我慌的同学还挺少。其实并不慌,因为我们准备了十几二十个预案,本来就是应对如果出现A问题就用A预案,出现B问题就用B预案。

3.2 QQ春节除夕红包:启动预案

刚才指出的问题在不在预案里面呢?基本都在。

  • 第一个,流量级别达到20万每秒,这时候就把非关键的请求取样,不让它上报,没有什么关联信息,通过这种方式把流量还降了回去。

  • 第二个,实时server挂了,这个东西也对用户来参加活动的流程没有影响,这个地方我们也是被说得比较惨,就是产品看不到真实的发货数据,比如10分钟发了多少礼包,本来是通过实时server来看的,所以对产品的意见比较大。

  • 第三个,是Cmem带宽跑满问题,这个问题真没法考虑,连预案都没做,运维同学早就把万兆网卡准备好了,我一直想着肯定有开发同学评估不到位,立马预案上了就换掉了。

  • 第四个,是消息堆积严重问题,虽然严重,但是我们早就考虑到万一堆积到不可想象的数量,我们支持了长期保存的方案,还故意扩了一些磁盘特别大的机器,得以不停的写,甚至可以在里面保留几天都没问题,对整体的业务效果是没有大影响的。

  • 第五个,是我们确实发现在链路里补货失败的,这个请求已经进来,应该给他发货,但是某个链路里又丢掉了,你不知道哪里丢掉的。最后我们通过对账补账把他们给补了。

通过前面的总结,我们的预案,准备的这十几二十个预案,我们抱着这样一个心态,如果这些预案一个都用不上,我们是很开心的,说明你的系统完全符合你的预期在线上跑了。

大家不要觉得这些预案很浪费时间,虽然真的很浪费时间,你总是假设我这个server挂了,假设存储挂了,每当加一个假设就要做一个预案,这个预案还需要耗费一定的工作,运维同学也是很辛苦,开发同学也很辛苦,但是这十几二十个预案真的出问题的时候,真的是救命的。

虽然我们希望这些预案一个都用不上,但是往往用上一两个都是救命的,如果我没有预案,遇到前面四个问题的话,我就真要被开除了。

3.3 QQ春节红包活动的反思

总结一下这些问题:

首先流量超预期,是少估算了QQ钱包的流量;

其次是业务集群隔离和分业务预估也做得不够好,游戏这边不受到影响,QQ钱包高负载,影响的范围不是红包集群了,整个都受到影响;

然后到扩容这边,虽然我自己常常讲三倍扩容原则,我们是9.6万的预估值,理论上要扩到30万每秒是比较安全的,但是我们为了省机器,最后只扩容到14.6万每秒的量级;

最后发现超预期了,所以就出现高负载场景。

所以有些原则该遵守的大家还是要遵守,也是我自己抱侥幸心理,这点我需要检讨。

另外就是实时 server 挂了,涉及到监控和产品业务数据,也是当时比较好提前考虑和纳入进来的。

最后是带宽,被跑满了,这也是我们梳理不到位,我关注一些静态资源,假设平时是两万每秒的系统,看看对应的存储大概的带宽情况,再用层级算一下预估量就有大概值,这个问题如果有做详细的梳理是可以梳理出来的,本来是可以做得更好的。

最下面这个图是其中外网的入网流量量级,5.1G每秒,这对静态的图片量级并不大,但是这不是图片,是前面前端的普通HTTP包头,没有任何图片,这样的请求达到5.1G,也从侧面反映出我们当天的峰值还是比较高的。

3.4 大流量活动的高可用建设经验总结

本文围绕了三个主题进行了分享,现在做个总结。

首先是怎么建设高可用的系统,在大流量的场景下,第一点是需要对系统架构进行梳理,首先你能够把整个系统架构以图的形式画出来,画得越细越好,每个环节每个子系统都画到,基于这样一个架构图进行功能点的链路梳理,一个领取功能涉及哪几个环节,有没有重叠的,全部都计算出来。

因为任何流量压力都有来源,要么是上广告,这个广告的曝光是多少每秒,再加上你历史得到的、演习得到的数字进行汇总和计算,这样就可以得出流量的压力。

还有 APP 可以算当天登录每秒的峰值,大家觉得 APP 可能难算曝光,APP 可以按登录人数算,最高人数比如是五千每秒,那就按五千UB来算,按这个值折算成你的广告曝光带来的流量。

所以通过这种方式当把流量预估出来以后,对架构进行扩容评估,但是扩容评估中肯定会遇到跟状态相关或者第三方不可控的系统,这些系统也没办法直接完成平行扩容,就需要对它进行合适的改造,根据前面共同探讨的几个原则改造,改造完了以后就可以根据可用性的几个原则,对它进行增强,过载保护等等六个原则进行增强。

最后一点非常重要,就是梳理你的紧急预案,可能你会得到好几个紧急预案,进行梳理,做好表格,做好开关,让当天晚上值班的同学把表格读熟,出现什么问题就用什么预案。当我们做完以后,这个系统就可以真正去参加大流量的流量服务了。

近期好文:

《一个关于Paxos算法的故事》

《8种常被忽视的SQL错误用法》

《腾讯1300场NBA直播背后的技术力量》

《5分钟让你了解 ZooKeeper 的原理》

《聊聊日志这件小事情》

《Docker跳反了,运维们还会继续用它吗?》

点击“阅读原文”,享受 GOPS·北京站 特价优惠

标签

发表评论