本期作者
武安闯
哔哩哔哩SRE工程师
2016年加入B站,深度参与B站微服务拆分、云原生改造、高可用建设、SRE转型和稳定性体系落地等项目。当前主要关注B站在线业务的SRE稳定性体系建设和推广,对SRE的实践有深入的探索与思考。
01 背景
B站每年都会有多次大型活动,如拜年纪、美的夜、LOL全球总决赛、电商626、919秒杀等其他活动。其中美的夜和LOL全球总决赛是在线流量高的活动。在S11总决赛过程中,全站整体平稳运行,无基础设施、组件故障和服务核心链稳定性故障,抗住了远超预期的在线人数和流量,直播同时在线人数突破千万。
一场成功的活动保障离不开多个团队的共同付出和努力。SRE在背后是如何支持保障这些活动并不断完善我们的活动保障体系的呢?接下来就为大家揭晓。
02 活动场景
案例1:
在SRE的某次活动保障中,突然听到运营同学说某某时刻微信、头条等APP会上线活动的推广链接。考虑到微信和头条APP的用户量级,SRE担心新用户到来会对基础资源和业务服务带来冲击。但因为事发突然,短时间大家也无法预估接下来的用户量级。所幸终推广带来的用户增长有限,未对活动产生影响。
案例2:
在某次活动事前沟通中,SRE从研发侧得知运营要在活动中对全站在线用户做一次站内Push:对打开App的所有用户推送一个App内的弹窗。此方式会快速推送到几千万量级的在线用户。如果用户点进活动链接,那瞬间带来的流量会击垮活动业务,甚至对我们的基础设施也会带来压力。SRE跟运营和研发三方确认后,认为此方案风险太大,终取消。
案例3:
在SRE的某次活动保障时,峰值流量已成功过去,活动保障进入收尾阶段,大家已经准备收拾东西下班了。突然多个服务发生报警,服务不可用。SRE紧急介入排查,发现是活动后运营做了一个推送,导致用户集中去访问一个非活动链路中的服务,此服务未纳入活动保障中,导致容量过载,服务不可用
还有非常多类似的案例。所以对SRE来说,为了能成功的保障一场活动,除了技术上的保障和跟研发沟通外,还要主动跟运营、产品确认活动形式、玩法、外宣方式等,SRE得离业务近一点。SRE目前会收集活动如下的信息:
活动形式
活动的具体玩法是什么:是一个直播间、还是一个秒杀、还是一个互动等,不同的玩法所需要重点保障的业务场景完全不一样。
重点场景
同一个活动,但重点场景可能不一样。比如某一场直播的重要场景是在线人数和弹幕,但另一场直播的核心可能是用户送礼和抽奖。
了解重点场景,可以指导SRE后续跟研发共建服务端保障的重点预估在线人数。
预估在线人数
活动本次预估在线人数是多少,如何预估出来的。
有哪些在线人数转化的路径。
活动对外链接
WEB、APP内的活动入口是什么?
站外有哪些引流入口?
了解用户访问路径,SRE才能做到全链路的可用性保障。
活动推送
活动中一共有几次推送?推送的形式是什么?用户转化率是多少?
活动后场景
活动结束时有没有特殊行为,比如直播间自动跳转点播页面?
活动后有什么运营事件、有什么二次热点?
这些事件所对应的用户访问路径和服务都需要SRE去重点保障,不然会有始无终,顾头不顾尾(这都是血泪的教训)。
时间线
活动前期上线、外宣、预热的时间线。
活动中的开始、推送、抽奖、口播、结束等时间线。
03 资源准备
根据前一步跟运营、研发了解的活动内容,我们已经知道本次活动预估的在线人数,根据此在线人数和历史活动的容量数据,我们可以初步预测本次活动需要的资源。SRE把资源分为两类:基础资源和业务资源。
基础资源
主要是基础设施对应的资源,如下,一般是要确认CPU资源和带宽资源:
DNS
DCDN(动态CDN)
静态CDN带宽
直播弹幕带宽
高防
源站四层LB
源站七层SLB
WAF
IDC-云专线带宽
IDC间专线带宽
NAT带宽
网络硬件带宽
-
日志/监控
在这里对后两项作出解释:
日志/监控:活动期间大家格外关注监控数据,需要基于监控数据来执行预案,所以监控的保障非常重要,需要纳入SRE的管理;日志类似,活动期间,查询各种数据,用户行为,业务异常等,也需要日志系统稳定。
网络硬件带宽:因为活动中业务流量突发,历史活动中曾出现过网络硬件设备带宽被突发打满的情况。所以对于业务的核心链路(机房入口—> 业务API GW —> 存储类服务 —> 基础设施)来说,确认这一步也非常有必要。
基于上面这些资源,会按如下的格式来确认信息:
使用容量和对应时间点
目前的使用水位
是否扩容、原因
弹性扩容方案、排期
扩容后水位
活动中容量预案
活动结束后方案
-
负责人
如下表:
经过如上的信息梳理,SRE跟基础设施各团队确定后续扩容方案,SRE对基础设施的资源已经有了全局掌握。接下来SRE会跟业务团队确认业务资源情况。
业务资源
业务所直接使用的PAAS、IAAS、缓存、DB资源等。一般需要确认的资源如下:
PAAS(容器资源)
IAAS(裸跑物理机资源)
CACHE中间件
MQ中间件
KV 存储
-
DB 存储
SRE构建了容量管理系统,可快速获取业务部门资源的整体容量和使用水位、剩余Buffer可用等数据,确认活动所需资源缺口。业务资源通过采购机器或者混合云来满足。待资源就绪后交付业务或交付给平台扩容,在业务使用时动态扩容或提前扩容即可,后续通过性能压测来验证预估是否符合预期。
04 压测&演练
性能压测
每次活动前业务都有多次压测,一般分为三轮。
轮:基于现有系统资源压力,发现系统瓶颈和待优化项(部分活动可能没有这一轮)
第二轮:资源交付、业务扩容、服务优化后按活动目标压测(每个活动都会有这一轮)
第三轮:所有优化方案和保障方案上线后,再次压测,验证预案的有效性和服务终能力,这次之后非必要需求不上线
在每轮压测中,SRE的关注点并不相同。
轮:
关注压测工具、压测链路是否稳定,是否满足活动压测需求;如压测肉鸡扩容;调整限流,以免拦截压测流量。
发现有性能瓶颈的服务、接口,跟研发一起分析瓶颈点。
确认中间件是否有性能瓶颈,如Redis 热KEY,DB 热点SQL。
-
发现跨部门上下游服务链路中的瓶颈。
这一轮的压测重点是关注压测工具本身和业务服务的性能瓶颈,跟研发一起确定后续的改进方案。
第二轮:
关注活动目标是否可以达到。
关注基础设施资源容量水位,确保安全。
关注业务资源情况,确保安全。
-
关注全链路上下游服务的瓶颈、中间件瓶颈。
这一轮压测会有多次,中间伴随着多次优化,直到满足活动目标,容量水位安全,各依赖服务不再成为瓶颈。
第二轮压测过后,活动业务系统基本已满足要求,SRE会跟研发确认各业务模块和接口的限流配置,并讨论限流执行的层级:七层SLB、业务API GW、服务框架层皆可支持限流配置。我们的佳实践是:
服务框架配置一个活动预期流量的限流阈值,基于活动实际峰值压力再动态调整。
API GW配置一个比服务框架宽松但保证服务不会过载的限流阈值。
-
SLB配置一个保护API GW的限流阈值,一般是API GW限流阈值的两倍以上。
在第二轮压测阶段,活动部门一般是关注自己业务场景的压测。但活动也会给其他的基础系统带来压力,如搜索、账号、支付等,SRE此时会跨部门协调这些业务团队也执行一次压测,确保各系统容量皆是安全的,万无一失。第二轮压测后,各种保障方案也会确定配置上线的时间。
第三轮:
第三轮压测不是必须的。对于有第三轮压测的业务,常见场景有三种:
比如S11,有1/8决赛,1/4决赛,根据前面比赛的真实数据,再次预估线上系统的总决赛压力,对线上的系统做压力复核,同时也验证总决赛前业务上线的需求性能。
在线上的各种保障方案上线后,再次压测,确保系统运行符合预期,如:HPA能自动扩容,各种限流可以生效,多机房分流符合预期等。
-
对服务做极限压测,观察服务的极限瓶颈,评估业务系统预期能支持的极限在线人数。如果业务支持的在线人数上限比较高,会给业务设置一个超出预期在线人数的限流配置。
这一轮压测中SRE关注的重点是线上保障方案是否有效,预案是否符合预期,业务第二轮的压测结果在这一轮是否能继续达到,以及是否要调整各种预案。
演练
这里的演练是指预案演练和故障演练,这里重点讲下故障演练。B站的故障演练,即混沌工程是在19年 SRE开始起步建设的,基于阿里开源的chaosblade工具打造,跟内部平台集成,目前支持:
节点级故障:既支持PAAS环境的K8S节点,也支持裸跑业务的物理机 IAAS环境。
硬件资源争抢:节点上的CPU负载、内存占用、磁盘占满、网络异常
上下游故障:服务间调用延迟、丢包、失败
-
中间件故障:服务调用中间件,如CACHE、KV存储、DB、MQ等延迟、丢包、失败
目前混沌工程平台既提供了面向研发、QA侧的控制面故障注入能力,也提供了集成到自动化故障测试的API能力。SRE基于建设的混沌工程平台,跟多个部门业务做了多期故障演练和自动化测试,如:
直播业务S11核心场景故障演练
UGC业务场景对中间件依赖故障演练
OGV业务场景上下游应用依赖故障演练
消息队专项故障演练
电商业务场景的自动化故障测试
-
......
累计执行故障演练3000+次,发现服务隐患200+,对提升服务的可用性有非常显著的效果。
发现的典型问题如下:
服务对下游服务应该是弱依赖,但编码成了强依赖
服务调用下游服务失败后,熔断或降级方案未按预期生效
服务调用缓存超时或异常时,接口失败,导致用户请求失败
服务调用消息队列失败,导致用户写操作失败
-
......
对于大型活动场景,我们所演练的故障场景也比较类似,如下:
-
服务上下游调用失败
服务间的强弱依赖是否合理,降级、熔断机制是否生效。
-
服务对中间件的调用失败
对中间件是否具有降级方案,降级方案是否生效。
-
服务所在宿主机节点故障
验证服务是否具有状态,是否可接受单点故障。
-
服务POD故障,POD里的某个sidecar故障
验证平台的failover能力是否符合预期,主容器对sidecar的依赖是否合理。
-
服务POD的CPU负载注入
验证服务的HPA策略是否生效,HPA策略是否合理。
通过故障演练,SRE既保障了服务的容量和性能,也进一步提升了服务的可用性,提前发现服务架构中的脆弱环节,同时验证了预案的有效性和监控、报警的准确率。
05 以史为鉴
在梳理我们的保障能力之前,SRE会先检查《以史为鉴》环节的内容。SRE会把之前活动保障中做的不好的地方总结为历史教训,形成checklist,确保本次活动中相同的问题绝不会再次出现,如:
之前活动压测遗漏了WEB端的服务链路,确保以后不会再犯。
活动期间,在离线混布没有关闭,对在线服务的突发有一定压力。以后活动时,要把在线核心业务场景的机器离线混布任务关闭。
活动期间关闭K8S的VPA策略,避免因为活动中服务压力增加,导致第二天服务的request增加,资源池无资源可调度。
活动核心链路上有服务未开启HPA,导致活动中需要手动扩容,效率较低。
.....
通过checklist模式的确认,SRE能确保相同的问题不会再次出现,这种模式类似于Google SRE中提到的《发布检查列表》。
06 技术保障
我们经常说业务高可用,也经常说业务可用性提升了,到底是业务运气好没出问题,还是因为我们的技术保障能力避免了业务出现问题?SRE到底有那些手段、能力、方案来保障业务的高可用呢?这里就来盘点下我们部分核心组件的业务保障能力。
DCDN
-
CDN缓存
如果业务可接受一定的数据延迟,可在DCDN上添加接口缓存,降低源站服务压力和带宽,如视频弹幕列表、直播礼物道具等。
-
多活服务的多机房分流
B站对于同城双活类服务的调度是在DCDN层面实现的。对于支持了同城双活的服务,DCDN可以动态调度多机房的流量比例。如果某个机房的服务出现问题,可快速切换用户流量到其他机房。
七层SLB
-
全局限流
△ B站的七层SLB基于OpenResty和部分自研功能实现。
△ 前面有提到SLB的限流能力主要是为了保护业务API GW不过载。对于没有API GW的服务,SLB限流直接保护服务不过载。
-
多活服务故障自动降级
△ 如果一个多活服务的单机房出现问题,为了业务快速止损,切量到其他机房是快的预案。
△ 如果在DCDN层面切量,是需要手动执行切量操作的,目前执行时间在5分钟左右。
△ 为了实时止损,SLB会发现服务所有机房的节点,如果某个机房的节点无法处理请求时,SLB会把请求自动降级到其他多活机房/可用区。
- 这种降级能力目前需要手动开启,适用于完整实现了同城双活的服务。
- 对于活动场景的核心请求,SRE会跟研发提前沟通,在SLB上配置此降级能力。
- 此自动降级功能后来也做到了API GW的功能里,实现原理比较简单,如下:
WAF
-
单IP限频率
可配置单个IP对某个URL或域名在一段时间内访问次数超过限制后封禁一定时间,一般用于接口防刷,用于保护服务端,提前拦截无用请求。
-
恶意IP封禁
可基于请求的某一特征,比如UA或者Referer,定向封禁活动中的刷子用户。
PaaS
-
HPA横向扩容:Horizontal Pod Autoscaler
△ PaaS平台是基于K8S构建的,支持基于服务的CPU、Memory、GPU等指标来弹性伸缩。
△ 有些活动的时间会比较长,流量增长比较平缓,比如直播LOL赛事,就很适合添加HPA策略,让服务容量根据压力动态伸缩。
△ 有些活动场景,比如电商手办的秒杀,活动持续时间是秒级,可能活动已经结束了,但HPA还没扩容生效,这种场景就不适合HPA。而是应该提前扩容容量,配置好限流阈值,做好容量保护。
-
VPA纵向扩容:Vertical Pod Autoscaler
△ 资源池总的可调度资源是有限的,如果在活动时有业务临时扩容或触发HPA扩容导致资源池无资源可调度,此时遇到BUG需要服务发布或其他服务扩容,岂不是就无法处理了?这里就突出VPA的重要性了(VPA的概念可参考K8S文档,这里不再赘述)。
△ 正常情况下,在线业务资源使用率是较低的,峰值CPU使用率不会超过40%。只要资源池整体CPU使用率是安全的,我们就可以动态调整服务的request,释放出资源给其他服务调度,这就是超分/超卖的逻辑。
△ 前面有提到SRE的容量管理系统,此系统同样支持对PaaS服务的VPA管理和动态执行,一条VPA策略的核心配置例如:选定一批服务,基于此服务过去1天cpu使用量的99分位值,设置cpu_used / cpu request * = 50%;此策略可立即下发生效。
△ 只要资源池总体CPU使用率水位是安全的,SRE就可以在服务无资源可调度时通过VPA能力快速释放可调度资源,大大提升了SRE容量治理的灵活度和控制力。
-
混合云
△ 如果资源池总体CPU使用率水位已经达到50%,此时不宜再用VPA能力继续超分。
△ SRE会给业务预留一个基于云K8S的资源池用作兜底扩容。如果IDC内的资源池容量不足,可10分钟实现云K8S节点初始化并加入云资源池提供调度。
Cache
-
容量保障
△ 数据层扩容一般耗时都比较久,建议业务基于前期压测,提前扩好足够的容量。
△ 如果需要紧急扩容,SRE建议临时增加单节点内存大小,尽量避免扩容节点。Redis扩容节点时Slot的迁移对业务有轻微的影响。
-
热KEY、大KEY监控
△ 如果服务使用了Cache proxy,可通过proxy侧的埋点数据来发现热KEY和大KEY。
△ 如果服务直连了Redis,可通过Redis平台临时采样抓取一段时间内的请求来分析热KEY和大KEY。
DB
-
服务降级
在主从延迟比较大的时候(大于 120 秒) 触发 DBA 的自动降级保护逻辑,牺牲一部分宕机场景的数据一致性( 大 1s),来提高从库性能。
-
异常拦截
服务接入DB proxy后,支持异常 SQL 黑名单拦截。通过此能力已多次在线上快速拦截慢SQL让业务快速止损。
-
负载均衡
把其他机房的从库加入到读负载,临时提高读请求的吞吐能力。
监控大盘
SRE跟监控、业务研发一起,做了活动全链路监控Dashboard,一般包含业务大盘数据、基础资源容量、业务监控、中间件监控等数据,内容会随着具体活动而微调。
此大盘在活动现场保障时会用于现场投屏,大家一起紧盯监控大盘里的异常。
上述保障能力是我们保障体系中核心的部分能力,完整能力不再展开描述。SRE也会跟业务研发团队盘点业务架构的上技术保障能力有哪些,这里不再展开描述。
SRE通过对上述技术保障能力的梳理,可以很清晰的知道目前我们有什么能力来保障活动的稳定性。SRE盘点完这些技术保障方案后,对SRE本身的能力也是一个全方位的提升。
07 预案能力
如果活动中出现了异常或者故障,SRE或业务研发团队该如何选择对应的技术保障能力,或者如何应急处理呢?预案能力的提前盘点也非常重要。预案是侧重于已经发生问题时快速止损的能力。技术保障能力和预案能力的区别是:前者侧重于问题发生前,后者侧重于问题发生后。下面列出SRE在活动保障中关注的部分重要故障预案。
上面这些预案只是SRE侧预案的一部分。除基础设施、组件类的预案外,SRE还会跟业务研发团队梳理业务侧的预案,业务侧的预案分为两种:
业务熔断、降级、限流等高可用类的预案
-
活动玩法、功能降级等产品体验类预案
对于技术预案,这里再多聊一下。常见的预案有:切量、降级、限流、回滚、重启、扩容等。在确定预案的优先级时,我们要从如下几个方面来考虑:
概率:TOP3类故障场景的预案优先
生效时间:生效时间越快,止损效果越好
是否有损:预案是否对业务有损,优先损失较小的预案
复杂度:预案执行的复杂度
幂等性:预案多次执行的结果是否一样,优先选择不确定性较小的预案
08 复盘改进
大型活动结束后,SRE会组织各团队做活动复盘总结,如S11总决赛。SRE会提供一份活动复盘模板,模板内容大致如下:
一、项目目标
本次xx活动,SRE团队的目标是:
首先,xx活动不能出现主流程事故。
其次,相关业务都不能出现主流程事故。
再者,不能出现基础技术事故。
二、过程回顾
这个阶段,我们的核心目标是做活动开始前准备阶段的复盘总结。千万不要只做活动中和活动后的复盘,活动准备阶段也有很多非常有价值的优化改进项。
三、数据总结
此阶段汇总活动中的一些核心数据,如终在线人数,基础资源使用容量水位、业务资源使用容量水位等。数据有两部分重要用途:
1. 用于后续活动中SRE做容量预估。
2. 基于数据曲线挖掘活动中的一些预期外行为,如带宽突刺,流量突刺等。
四、问题复盘
这个阶段,SRE会记录活动中出现的问题,并做复盘总结,确定后续改进方案。活动保障中所产生的Todo,SRE会专项跟进,定时确认进度,确保优化方案都执行落地。
五、反思总结
这个阶段,SRE会思考整个活动保障项目中做的好的一面,不好的一面,进行整体的反思。比如活动后资源的回收目前就做的不好,后续需加到活动保障流程中去。同时也会重点更新我们活动模板中的以史为鉴checklist和其他内容。
09 总结展望
对SRE来说,参与一次活动保障,可快速了解整个系统中的基础设施、组件能力、技术保障、预案、应急响应等,个人技术能力和综合能力会得到极大的提升。大型活动同时也是对基础架构和技术保障的一次大练兵。通过上述的活动保障体系,SRE已成功保障了B站近几年所有的大型活动,包括流量远超预期的S11总结赛千万级用户在线。在目前的保障中,部分保障措施还未自动化,人耗较高,如基础资源的梳理。后续要把保障体系中人工的工作部分沉淀到活动保障平台中,让SRE可以更高效的保障大型活动。
后,期待今年美的夜和S12,再创新高!