查看原文
其他

S11全球总决赛B站直播在线稳定性保障简介

直播技术团队 哔哩哔哩技术 2023-11-25


01




背景


2021年11月7日凌晨,在《英雄联盟》S11全球总决赛·决赛中,中国战队EDG对战韩国战队DK,经过5个小时5轮比赛,EDG最终以比分 3:2 击败DK,赢得S11总冠军。B站作为英雄联盟2021全球总决赛直播独家版权方不仅在整个比赛过程中保证了直播整体总体运行的平稳,还抗住了超预期的流量,观赛人数破亿

02




大型活动的稳定性如何保障


为了保障这场活动的稳定性,我们投入了近4个月的时间,上百人参与其中。不但保证了S11的正常播出,同时我们也以S11稳定性保障为例,总结出一些稳定性保障的方法论

2.1 总体规划
项目保障工作从7月开始,一直持续到决赛结束。

在总体方案输出之前,我们先设定了16条规范,对一些常见的风险,包括:非数据服务做到无状态,避免同一集群内的节点间有功能差异;线上服务最小集群单元2个实例,避免单点服务;服务的所有依赖库或者服务都要有明确的负责人,依赖服务需要有完备SLA等等,这些前期的规范准备,这也为整体项目顺利实施奠定了基础。
总体规划包含Web端、移动端、服务端、运维、直播流、采购等多类型事务;同时涵盖了公司8个以上的团队;10余项大项执行项目。
为了给到用户最佳的视听互动体验,我们反复打磨每一个使用场景、进行多轮压测、混沌测试、预设降级策略、限流策略、设定预案/SOP、临场保障等,从而保证该赛事直播的顺利进行。

2.2 场景
对于多数研发来说,关注的仅是自身服务是否可用,但是由服务串联成的场景才是实际用户感知的使用过程。
定义场景能帮助我们更好的识别场景、理解场景、利于保障,是保障的基础。我们将场景的定义罗列为以下5项:
  • 场景名称
  • 场景级别(P0、P1、P2、PX)
  • 设计终端(iOS、Android、Web、PC)
  • 场景描述(使用5W1H方法,即谁Who在什么时间段When在什么页面Where做什么事What,原因是什么Why,如何做How)
  • 场景交互(使用图来表征)
我们根据这样的定义,共梳理出40+个场景。

2.3 流量预估
系统的压力来自于海量用户每一个行为的流量。梳理好场景后,我们需要从入口梳理出每个场景的流量,也就是这个场景需要承受的QPS,然后再具体到这个场景涉及的每个接口的QPS,如进入直播房间场景:
从上图,我们总结出进房场景涉及的服务和接口以及对应的QPS。这里有必要说一下QPS的预估方法,主要有两种:
  • 历史流量算法:根据当前&历年活动流量,计算整体业务体量同比增量模型。
此算法比较适用于一些老的场景,老的接口。
  • 业务量-流量转化算法(GMV\DAU\订单量):一般以业务预估总量(GMV\DAU\订单量)为输入,根据日常业务量-流量转化模型(比如经典漏斗模型)换算得到对应子域业务体量评估。
此算法比较适用于一些新的场景,新的接口,特别是本次活动新增的。

2.4 压测
保障系统稳定性最大的难题在于容量规划,而容量规划最大的难题在于准确评估系统的实际承载能力。通过压测可以评估系统的实际承载能力。另外,高并发时,压测可以检测到一些在流量比较低的时候发现不了的问题。
这次我们共进行了三轮压测,每轮压测都会执行多次:
  • 第一轮:先不扩容,压出系统的极限,找出瓶颈和优化点
  • 第二轮:等系统优化和业务需求做完,扩容后,按照S11预计流量压测
  • 第三轮:验证,回归,查漏补缺
经过多轮的压测,我们也总结出了压测时应该注意的问题:
压测前
  • 确定场景下所有要压测的接口,如果有的接口不太容易压测(比如会产生脏数据)暂时先不压测,但是后期需要做预案(比如如何保障,出了问题怎么办,降级方案是什么)
  • 打开接口限流
  • 压测信息周知到你依赖的服务的负责人,如果涉及Mysql,Tidb,Redis,MQ等同样需要周知到对应负责人
  • 如果多个场景对同一个服务都依赖,那多个场景需要一起压测
压测中
  • 开始要缓慢施压且控制压测时间(比如1分钟),以防止出现问题。
  • 紧盯各项监控(服务的监控,Redis,Mysql,Tidb,MQ等),如有异常,立即停止压测
  • 遇到日志报错增多,立即停止压测
  • 遇到接口耗时明显增加,立即停止压测
  • 资源(服务器,Redis,Mysql,Tidb,Databus等)逼近极限,需停止压测
  • 多轮压测,步步提升QPS
  • 保证压测流量均衡
  • 记录压测过程中不同压测QPS下各项资源(服务器,Redis,Mysql,Tidb,MQ等)压力情况,以供后续分析
压测后
  • 查看各项监控,服务是否健康,QPS是否正常,保证服务没有问题
  • 如果有临时数据,是否要清除

2.5 混沌工程
虽然压测已经做过,但这只是在系统正常运行情况下的表现。真实情况中,线上系统经常会出现各式各样的异常,那么我们能否主动找出系统中的脆弱环节,提前做加固、防范呢。这里我们引入了混沌工程,那么什么是混沌工程呢:
  • 分布式系统有着各种相互依赖,可能出错的地方数不胜数,处理不好就会导致业务受损,或者是其他无法预期的异常行为[1][2]。
  • 我们应该致力于在这些异常行为被触发之前,尽可能多地识别风险。然后,针对性地加固、防范,从而避免故障发生时所带来的严重后果。
  • 混沌工程在生产分布式系统上进行实验,主动找出系统中的脆弱环节。通过实证的验证方法为我们打造更具弹性(弹性:系统应对故障、从故障中恢复的能力)的系统。
本次混沌实验的目的:通过故障注入,验收证明全链路的高可用性, 包括监控、告警、定位、恢复体系。主要聚焦在以下几个最常见的故障场景去做演练:
  • DB不可用/不稳定(超时,抖动等)
  • Cache集群不可用/不稳定(超时,抖动等)
  • 依赖的RPC服务不可用/不稳定(超时,抖动等)
  • 网络抖动
  • 宕机
以下为本次我们的推进过程:
  • 梳理整个系统的部署架构图,如下所示:
根据部署架构图,可以清楚地看到服务所依赖的各种资源的关系,这样就可以根据部署架构图在每一个调用链路上设置故障点。
  • 设置故障点
根据部署架构图,可以设置DB不可用/不稳定,Cache集群不可用/不稳定,依赖的RPC服务不可用/不稳定,机器宕机,网络抖动等故障
  • 故障演练
演练由测试同学在任意时间触发任意故障,然后记录开发同学可否1分钟发现故障,五分钟定位故障,十分钟解决故障。同时记录故障演练的过程,参考如下:
根据以往经验,故障演练可以分至少两轮,第一轮对所有故障点进行一场演练,演练完之后进行系统优化,第二轮可以采取”考试“模式对故障点进行抽检。

2.6 降级
降级目的是削弱非核心服务资源占用,保证业务核心服务稳定性。降级策略有很多方面需要思考与落地,在这里总结一下经常用到降级策略。
  • 页面降级:非核心页面模块,占用紧张资源,关停该页面,减少访问;
  • 服务降级:将功能分类,分为核心服务与非核心服务,将非核心服务进行关停;
  • 依赖降级:将依赖服务梳理分类,保证核心依赖的稳定,将非核心进行降级关停;
  • 读写降级:将直接读写数据库切换为读写缓存;对于缓存依旧可以进行备份冗余;
  • 延迟降级:页面的异步加载策略;数据写入异步消息队列等。
降级的实现方式,大体分为两种,一种是自动降级,一种是主动降级。
  • 自动降级:
  1. 一般可以通过代码层面处理,比如调用接口返回了err,对于golang,我们可以判断err是否为nil,如果不为nil可以进行降级处理,如果是Java,出现Exception,可以在Catch中处理。
  2. 也可以通过熔断器进行自动降级,但是需要考虑好熔断的阈值。
  • 手动降级:一般通过开关处理,开关的实现有很多种,比如配置中心。
  • 了解了降级方法之后,我们还需要清楚不是所有服务都能降级,也不是等到故障发生了以后,才去选择或者确定哪些服务可以降级。故障的降级策略一定要提前规划与思考。
    系统或者服务需要分为核心和非核心。核心服务是我们力保不能有任何问题的主流程服务 P0;非核心服务,又可以根据重要性进行再次分层。可以划分为 P1、P2、P3 服务:
    • P0 服务为主服务,是力保稳定性的对象,他们挂了整个业务也就崩溃了;
    • P1 服务为与紧密主服务相关,但可以后续异步补偿来操作的服务,比如说,结算流水,订单统计;
    • P2 服务与主服务有点相关,但关闭了对主服务任何业务逻辑没有影响,比如说,订单评价,商品推荐等;
    • P3 服务与主服务没有相关,关闭之后对主服务没有任何影响,比如说,广告推荐,用户喜好,评论浏览等。
    在梳理服务等级的时候,需要注意 2-8 原则,也就是 20% 为核心系统,80% 为非核心系统。因此我们主要精力要放在20% 的核心系统。
    在本次S11稳定性保障中,我们做了一定的降级策略如:
    • 直播首屏场景,正常情况下,会走算法推荐,但是如果算法推荐出了问题,通过开关切到简单排序规则
    • 用户心跳场景,正常情况下上报间隔是一分钟上报一次,如果出现资源问题,可以在配置中心,修改上报间隔到5分钟

    2.7 预案/SOP
    要想在大型活动的高并发流量场景下,快速对线上紧急事故进行响应处理,仅仅依赖值班同学临场发挥是远远不够的。争分夺秒的情况下,无法给处理人员留有充足的策略思考空间,而错误的处理决策,往往会导致更为失控、严重的业务与系统影响。因此,要想在现场快速而正确地响应问题,值班同学需要做的是选择题,而不是陈述题。而选项的构成,便是我们的预案。
    保障S11顺利播出,我们对每个场景整理了一套处理问题的“标准作业程序”,也就是所谓的SOP。
    每一个SOP大致有下面四点:
    1. 我们需要确定每个场景的模块出现问题的表现;
    2. 确定问题出现了,我们要确认该怎么做;
    3. 谁来做;
    4. 怎么做。

    2.8 限流
    大型微服务架构中的任何服务节点,不管怎么优化,怎么拓展,都会有能力上限。如果达到能力上限,系统服务崩溃的可能性就会增加,这种情况也很容易造成整个微服务应用的雪崩效应。

    当服务器的压力剧增的情况下,为了保证服务不被拖垮,对一些流量采取拒绝或者降级的策略,以此来保证核心服务的正常运转。这是一种有损的技术手段。

    因为限流是一种有损的技术手段,而且平时使用的情况不多,所以如何决策是否要做出限流操作,在S11的活动中我们做了如下定义:
    大前提:流量的突然增加,或者依赖的资源(比如存储层)有异常(可能是流量突增导致也有可能是存储抖动导致)且对业务有损,短时间没有有效的恢复手段,系统无法承受当前流量,且认为限流可以缓解当前情况
    举个例子:
    • 存储资源(Mysql,Redis等)问题:比如Mysql等资源出现不可用情况(比如,cpu跑满,大量超时或者大量慢sql)且没有恢复迹象
    • 流量突增:在某些情况下,你认为流量导致的问题,比如流量突增
    • 外部接口耗时增加:如果系统调用外部接口,外部接口突然出现耗时增加,导致系统服务器的cpu跑满,导致系统不可用
    限流不是目的,只是解决当前紧急情况的一个手段,并且对系统是有损的,所以要持续关注限流的效果和对系统的影响,并且及时解除
    本次S11,我们分别对核心接口做了:
    • SLB限流配置
    • Ekango限流配置
    • WAF单IP限速

    2.9 临场保障
    临场保障主要有两部分:
    • 确定值班人员,明确其支持位置
    • 现场保障与事故记录,现场保障的人员,需要时刻盯紧监控大盘,日志,和告警。如果出现了事故需要对应人员来记录处理状态,并且在群中上报处理进度。

    03




    总结展望


    本文我们以S11为例,介绍了大型微服务架构后台应用系统稳定性技术策略,通过我们的每一个实践总结了一定的方法,希望可以为读者带来一定的帮助。每个技术点都需要我们持续的思考与落地,全面整体的思考稳定性相关的建设动作。本文对S11全球总决赛B站直播在线稳定性保障做了简介,后续我们还会发表《S11全球总决赛B站直播在线稳定性保障揭秘》敬请期待。

    参考文献:
    [1]Betsy Beyer, Chris Jones,Jennifer Petof & Niall Richard Murphy. Site Reliablility Engineering
    [2]https://sre.google/sre-book/table-of-contents/

    顺便做个广告呦~
    B站直播技术团队大量岗位持续招聘中,诚招客户端(IOS,Android)/前端/服务端/音视频技术研发,坐标上海。欢迎感兴趣的同学加入我们。可投简历至:lvfan@bilibili.com(邮件主题请注明:B站直播技术团队)


    继续滑动看下一个

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存