1.前言英雄联盟全球总决赛是年度最盛大的电竞赛事,万众瞩目在中国。11月6日,DRX战队以近乎奇迹的方式从入围选手一路夺得S12全球总决赛冠军。非常鼓舞人心,恭喜DRX!B站是今年S12的官方直播频道,哔哩哔哩的活动直播间实时人气一度突破3.1亿。如何在整个S赛的洪峰流量下保证系统的稳定性和流畅性,给我们带来了巨大的挑战。为此,我们在7月底专门成立了S12技术支持项目,并开始了长达3个多月的紧张技术准备工作。我们的目标是实现“喝茶有保障”。2、如何实现经过盘点,我们将S12技术支持所依赖的各项工作分为赛前、赛中、赛后三个阶段,如下图所示:1.项目启动S12技术支持需要公司多个技术团队紧密合作,涉及业务研发、SRE、基础设施、DBA、大数据等近300人,在充分收集上游业务S12相关信息后,召集所有相关团队负责人召开项目启动会,最终就S12技术支持目标达成一致,力求做到统筹协调。2.资源预估1)业务适配为了最大化资源的使用价值,提高资源利用率,我们将业务目标PCU(最大在线用户数)、后续宣传策略和规划与上游业务进行对齐,因此技术方面可以及时介入准备并做出合理的资源估算。2)从B站SRE容量平台合理估算S11服务器去年的峰值使用量和去年8月份的每日峰值使用量b,粗略计算出同一个增长因子delta=(a-b)/b+1时期。同时求出今年8月的日峰值使用量c和当前服务器可用性d。因为我们要求服务器容量的安全水位在40%以下,资源缺口=c*delta/0.4-d。产品功能在保障过程中也会增加,因此这部分新增功能所需的资源支持将在单独评估资源缺口后追加申请。3、资源池管理去年之前,直播资源池是直播专属,独立于其他部门。当直播资源池资源耗尽时,需要从其他资源池协调机器->网络测试->机器初始化->重启标签进入直播池是人工操作,效率很低,经常会导致拥堵在线业务发布或扩展,影响应急响应效率。从全站来看,大型活动直播后,大量用户会从直播间切换到社区其他服务(稿件、评论、专栏、新闻等),类似到“潮汐流量”,这部分服务器冗余可以通过池化Book来“减少”。池化的前提是机器运行时的标准化:1)服务到CPUSET。由于直播的实时性和对延迟的敏感性,我们的业务场景无法接受CPUThrottle大概率导致的超时。大量的服务使用了CPUSET的核心绑定策略。CPUSET不能共享资源,不能合并池,造成一定的资源浪费。Kernel同事协助排查,发现PHP服务CPUThrottle大概率是因为同时并发执行的R进程过多,导致CPUQuota被击穿。查看PHP基础库发现PHP直播服务采用Swoole多进程模型,基础库会在每个Worker进程中设置定时器更新配置,1s检测一次,多进程多半会被唤醒同时。修复方案有两种:1)打乱进程定时器执行的随机性,减少“碰撞”;2)更新基于inotify的配置,丢弃基础库定时器。因为业务代码中也使用了大量的定时器来预加载内存中的直播热点数据,所以最终采用方案一,更新基础库后效果非常明显。protectedfunctionfuncWorkerStart(){returnfunction(\swoole_server$Server,$iWorkerID){//有些服务会在init_callback中注册workertimer来做配置加载//但是会带来太多并发R导致cputhrottle,这里做随机睡眠10-500msmt_srand((microtime(true)+posix_getpid())*10000);usleep(mt_rand(10000,500000));主::初始化();//配置文件周期性加载function()use($C,$Server,$iWorkerID){app(Metrics::class)->flush();//加载配置...//配置检查...//重新加载worker...};//注册定时器swoole_timer_tick(1000,$config_reload_cb);};对于Golang服务,我们引入了automaxprocs来自适应调整LinuxCFS调度模式下的GOMAXPROCS,并对所有Go服务进行代码lint检测。2)升级宿主机内核。直播中部分老机器内核版本过低,无法参与pooling,存在cgroup泄露问题[1],导致业务超时抖动。为了合并池后不影响其他部门的在线业务应用,需要对旧内核机器进行内核升级。B站操作系统团队统一了内核版本,杜绝了长期困扰业务的cgroup泄露问题。同时,基于GroupIdentity,优化了线下业务混合部门的CPU隔离。完成直播PaaS的池化后,缓解部门间机器多冗余带来的资源浪费。线上业务使用B站SRE容量管理平台按需分配,大大提高了资源利用率。4、业务场景拆解1)确定保障范围。经过8年的发展,B站直播已经具备了丰富的直播间玩法和能力,能够支持不同类型的直播场景。今年的S12我们也推出了很多新的玩法。涉及到的各种能力会在相应的后台配置完成后呈现给用户。不同的功能玩法由不同的技术团队支持。干练新玩法(共30+),划定保护范围。2)确定场景分级及分级标准如下:①P0部门核心用户场景对应的业务:需满足月均DAU>=xxW;不满足条件,降级为L1部门营收业务:需满足月均日营收>=xxW;不满足条件,降级L1虽然不满足上述要求,但业务属于公司战略方向,对下游业务强烈依赖②P1部门L0主业务场景的主业务核心不满足二级业务要求的L0部门核心用户场景对应不满足L0要求的行业。该部门的主要收入取决于下游业务。③P2部门向用户提供的其他行业依托于下游业务。定义业务分类标准,根据场景划分确定保障等级。最终根据S12涉及的30+功能拆解了10个P0场景、16个P1场景、9个P2场景。针对P0、P1场景,重点关注混沌工程测试、客户端性能测试、服务端性能压力测试、生产多活演练、可观察监控等,确保服务架构的高可用。3)梳理场景图①定义场景拆解后,针对单个场景全局梳理关联的业务逻辑(微服务调用关系、接口依赖等),形成场景图,帮助场景负责人和决策者快速了解服务本身的依赖情况。②梳理标准场景名称:xxx场景级别:P0/P1/P2场景引入方式:通过抓包、代码审查、负责人确认明确以下内部方式:5w2h方式(Who/When/Where/What/Why/How/Howmuchscenedependency:interfaces,services,caches,databases,messagequeues有了场景图,S12的技术治理和优化会更有针对性。一方面,深化开发和测试,随着对场景逻辑的理解,一些历史问题也会变得清晰;另一方面,这些元数据将有助于优化监控元数据的技术架构和校准。5.微服务之间的交互高可用架构的分布式架构调用非常复杂,一个点故障极有可能影响整个链路的稳定性,为此我们做了相当多的准备体系结构演变的ations。1)单点治理的分布式架构下,单点本身不具备容灾能力,最容易出现问题。应优先处理,主要包括:应用单点:要求所有应用部署多实例(>2)。JOB单点:基于XXL-JOB直播分布式任务调度系统二次开发,有效解决JOB无法多实例执行,碎片化的问题。单点资源池:直播PaaS资源池单宿主机巡检,避免某台机器单点故障后应用重新调度成功。2)高在线自适应防护在千万级直播场景下,一场直播结束后会有大量用户退出直播间并返回流量入口页面,这会给其他网关带来数倍的压力和下游。因为Prometheus监控有采集窗口,实际请求“glitch”比下图高。从流量转化数据来看,80%的请求其实是不必要的,用户可能已经关闭了APP。针对这种情况设计了高在线自适应降级保护方案。通过服务端与客户端的连接,可以直接从源头上避免用户不必要的热点行为和对后端服务器的流量影响。目前已经推出的保护策略如下。识别当前直播间热点后:退出直播间,不自动刷新流量页面。对于不重要的KV配置和其他请求,做随机延迟分解。对于集中广播触发接口热点请求,做随机延迟解散。分散动态增加离线数据上报间隔,降低服务器压力,API网关限流后自动触发客户端流控,微服务相互依赖,可能产生异常连锁反应。我们应该努力在这些异常行为被触发之前,尽可能多地识别出风险,然后有针对性地加强预防,避免一旦发生故障会造成严重的后果。混沌工程就是这样一种方法论,它通过在分布式系统上进行实验来主动找出系统中的薄弱环节。这种实证验证的方式可以为我们打造一个更加健壮的系统,同时可以让我们更加透彻地掌握系统运行时的各种行为规律,也可以在运行过程中及时、有针对性地完成系统规划。过程。B站从去年开始就引入了混沌工程。基于chaosblade二次开发,融合监控和问题管理,形成初步满足业务微服务治理的故障注入平台。但逐渐发现chaosblade只能控制端口级故障,爆炸半径太大,影响太大,无法在生产环境中实施。今年我们自主研发了控制粒度更细、爆炸半径更小的混沌演练平台,可以在接口和用户粒度上控制故障。详见下图:针对S12核心L0/L1场景,我们在进房、送礼、弹幕、首页等场景进行了故障演练和红蓝对抗,主动发现并管理了多类突发问题核心链接:代码问题,将弱依赖误实现为强依赖,导致核心链接失效;弱依赖不考虑降级方案,用户体验不好;代码问题,弱依赖的降级方案没有生效;对于强依赖故障,客户端是否可以实现容错,友好提示,各端降级体验是否一致。4)同城双活机房故障往往是灾难性的,会大大降低用户体验,甚至引起客户投诉,对用户和企业来说都是巨大的损失。多机房的故障转移能力非常重要。我们针对直播核心业务场景(首页、进房、送礼、预播等)实现了同城双活,进行决策和切换流,最大程度保证用户体验不受损.借鉴去年“B站713失败经验教训”,SRE平台和基础设施团队开发了Invoker多活流媒体平台。经过多次停产演练和验证,单次停产平均时限在5分钟以内。截流效率大大提高,避免了故障影响区域的不断扩大。5)网关迁移第一代APIGateway基于Envoy二次开发,部署在IDC物理机上。当资源估算出现偏差时,现场扩展非常耗时。需要服务树挂载->审批->机器初始化->运行时初始化->灰度->收卷→测试→SLB灰度→全SLB,平均耗时30分钟+。去年S11总决赛踩到这个圈套了。当时手速扩充到8个单位需要20分钟。扩容之后,一波爆款流量差点炸开。CPU峰值达到90%,非常危险!同时,Envoy网关是用C++编写的,代码结构非常复杂,调试困难,维护困难,无法一键部署。今年,我们将核心服务的BFF(BackendForFrontend)全部迁移到新的自研GolangAPIGateway。主要优势有:支持容器化部署,支持HPA自动弹性伸缩,分分钟完成扩容!拥有快速便捷的控制面能力:限流、降级HA:支持逻辑/物流集群隔离,支持全链路灰度。目前该项目已经开源,感兴趣的可以学习:https://github.com/go-kratos/gateway6。性能压力测试经过前期的优化,我们已经初步保证了整个技术库的抗故障能力。接下来,我们将通过多轮周期性压测来验证核心业务场景的极限QPS是否满足要求。需要分析瓶颈,做技术优化/扩展。1)压力测算目标每次大型比赛结束后,我们都会对比赛过程中的关键数据进行归档,以便对明年的目标值做出合理预估。根据去年业务数据(在线用户数、营收数据)的增速和核心接口的峰值QPS,结合接口的实际调用时序,很容易估算出本次接口的预期QPS年。假设去年同期最高在线N,A接口峰值QPS=a(A接口进入直播间必须调整一次,与在线人数线性相关),我们将业务数据目标与上游业务方对齐(同时在线最高=M),那么今年A接口预计承载QPS=a*(1+(M-N)/N)2)压测plan通过抓包和codereview梳理出今年S12核心场景的最新接口依赖关系和调用时序关系(串口或并口),哔哩哔哩自研压测平台Melloi支持同一场景下相关依赖接口的编排。今年的S12加入了很多用户玩法功能,为用户带来身临其境的互动观赛体验。涉及到很多写接口的压力测试,可能会对生产环境造成数据污染,产生舆论和客户投诉。B站去年自研全链路压测方案,通过全链路压测标识Context,并在数据写入层SDK中实现拦截策略,将压测写入流量转发至“镜像”数据隔离层”。实现压力测量数据隔离。压测结束后,压测平台对接数据库、缓存、消息队列等数据平台,快速恢复数据。S12送礼、心跳等直播核心写作场景均采用该方案。通过场景相关环节的上下游改造,借助全链路压测平台,真正确定数据库和异步JOB/Consumer的负载限额,设置负载限额。合理的限流有效保障了大型事件中写入服务的稳定性。3)压测执行为了保证压测数据的真实性,我们选择在低峰期在生产环境进行集中泄压。压测虽然是在低峰期,但还是有一些正常的用户流量,所以一定要注意避免把整个系统压垮:一开始要慢慢加压,压测时间要短(例如,1分钟)以防止出现问题。随时关注各种监控(服务监控、Redis、Mysql、Tidb、Databus等),发现异常立即停止压测。资源使用率接近极限,需要停止压测。记录压测过程中各种资源在不同压测QPS下的受压情况,以供后续分析。4)压测报告压测结束后,我们会系统整理压测报告:压测结果、目标回顾、问题跟进等。①常见问题②扩容最佳实践压测结束后,使用下面的公式来合理估计要扩容的副本数。7、保障方案保障方案主要分为业务层和技术层两个方面。1)业务计划通过场景图整理、混沌工程、性能压力测试,发现并管理了很多技术风险点。回顾针对这些问题的关键环节的技术优化,大部分链路降级调整依赖于各种配置:服务配置、KV配置、上下游配置。为了保证在整个S12过程中及时响应,关键环节不出问题,我们梳理了各个场景下可能需要现场执行的各种预案。我们针对15个S12核心场景制定了保障计划。部分方案需要多位现场负责人联动协调,我们将进行线上线下方案演练,验证效果。2)技术方案①网关限流:结合之前压测的QPS,配置合理的限流QPS②ServiceQuota限流:支持Zone和Caller限流③网关降级:支持通过PATH和Query/Header直接降级,将不把压力传递给业务服务BFF④资源弹性HPA:全称Horizo??ntalPodAutoscaler,水平自动伸缩。当业务PODCPU/内存使用率超过设定阈值时,自动触发扩容,无需人工干预。混合云:防止自建IDC机房资源用完,自动跳转到第三方混合云资源,充分保证资源的可用性。8.质量控制S12复赛后,我们推出了S12复赛管控升级。强管控期间,上线变更需谨慎,并报S12技术支持项目组审核检查。具体分为两个阶段:9、现场保障1)可观测性在往年大型赛事的保障活动中,投屏监控面板无法直接检测到系统问题,业务监控蔓延在每个角落,这使得故障排除非常不方便。今年我们首先根据场景图梳理出S12L0/L1场景的核心依赖:接口应用数据库缓存消息队列,然后围绕核心业务指标PCU(最高数在线用户数)、核心场景SLO、核心应用饱和度。新的健康监控监控仪表盘,每分钟自动更新一次。①业务核心指标PCU直播大多数系统与PCU呈线性相关,一旦出现波动,立即关注下游负载情况。②核心场景的SLO作为结果指标,对微服务失败的引导具有决定性作用。肯定是波动有问题。如果你对B站SLO体系的搭建感兴趣,可以阅读:还没搞清楚SLO,你是什么SRE?③S12核心应用饱和度作为预警指标,分为三个档位:红色:异常,需要立即干预橙色:高,需要关注绿色:健康,不需要关注问题是警报。我们目前的告警存在告警级别不明确、告警对象不准确、处理状态不透明、告警风暴等问题。告警治理将长期基于SLO。短期内,我们自研了一套告警应急协同平台,方便研发和SRE协同处理告警,一目了然。支持场景管理支持告警订阅:按告警I支持告警过滤:按告警ID、按告警权限支持告警聚合:同一告警在10分钟窗口内自动聚合支持告警处理协同:告警处理流程状态一目了然一目了然,方便协作①现场指挥员问题优先级判断应急响应技术判断与决策②值班人员业务:运营、审计技术:研发基础设施:SRE、DBA、网络工程师三、总结与展望过去这几年,S赛的技术支持现场,大家手忙脚乱地处理告警(扩容、限流、降级),现场一片混乱。甚至在直播结束后,报警和问题反馈也不断。今年,我们保证了整个S12直播期间,技术系统稳定流畅,没有任何需要主动限流、降级、熔断等技术介入的“茶保”。未来我们将回顾技术支撑过程中的各个环节,持续打磨技术中间件和平台,构建多活单元化,全链路压测覆盖,优化资源池调度,全面推进云原生落地哔哩哔哩基础设施。
