我们是北京华网天下科技有限公司,为您提供其中一项业务为:哔哩哔哩视频排名优化提升,和哔哩哔哩下拉词优化。
哔哩哔哩短视频排名优化,就是您发布的视频,在哔哩哔哩有排名,只要有排名,都可以进行优化到前3名。下拉词就是通过哔哩哔哩搜索时,能够让用户看到您的品牌名或者联系方式,也就是行业的热点搜索词,提升曝光度。您可以进入我们的公司官网或者联系商户经理微信ysfsyt1
B站视频排名优化提升【哔哩业务-商务合作-请进】B站视频排名霸屏B站 2021 年 7 月 13 日故障复盘:至暗时刻的紧急处理与初因定位
至暗时刻
2021年7月13日22点52分,SRE收到大量服务、域名接入层不可用告警,客服端开始收到大量B站无法使用的用户反馈,同时内部同事也反映B站打不开,甚至APP首页都打不开。根据告警内容,SRE第一时间怀疑是机房、网络、四层LB、七层SLB等基础设施出现了问题,并紧急召开语音会议,拉各team相关人员开始应急处理(为了方便理解,下文事故处理流程做了部分简化)。
初始原因定位
22:55 远程在家办公的同学登录VPN后,无法登录内网认证系统(B站内部系统有统一的认证体系,需要先获取登录状态才能登录其他内部系统),导致内部系统无法打通,无法及时查看监控、日志定位问题。
22:57,公司Oncall上SRE同事(未开启VPN,重新登录内网认证系统)发现在线业务机房七层SLB(基于OpenResty构建)CPU 100%,无法处理用户请求,其他基础设施均未报告问题。此时确认是接入层的七层SLB故障,排除了SLB以下业务层的问题。
23:07在家的学生紧急联系负责VPN及内网认证系统的学生,了解到可以通过绿色通道登录内网系统。
23:17 相关同学通过绿色通道登录内网系统,开始协助处理问题,此时处理事故的核心同学(七层SLB、四层LB、CDN)全部到位。
故障停止
23:20 SLB运维分析发现故障过程中有突发流量,怀疑是流量过载导致SLB不可用。由于主机房SLB承载了所有在线业务,因此重载SLB未恢复。随后拒绝用户流量,冷重启SLB,冷重启后CPU依然100%,未恢复。
23:22 根据用户反馈,多活数据中心服务也不可用,SLB运维分析发现,多活数据中心SLB请求大量超时,但CPU并未超负荷,准备重启多活数据中心SLB试图止损。
23:23 此时内部群里的同学反馈主站服务已经恢复,观察多活数据中心的SLB监控,请求超时次数大幅减少,业务成功率恢复到50%以上。此时多活业务的核心功能基本恢复正常,如APP推荐、APP播放、评论&弹幕拉取、动态、关注、影视等。非多活服务还未恢复。
23:25——23:55 针对未恢复的业务,没有其他立即有效的止损方案,所以此时尝试恢复主机房的SLB。
创建新的源站 SLB
00:00 在SLB运维人员尝试回滚相关配置仍无法恢复SLB后,决定重建一个新的SLB集群,并让CDN调度故障业务的公网流量,观察是否可以通过流量隔离的方式恢复业务。
00:20 新的SLB集群初始化,开始四层LB和公网IP的配置。
01:00 新SLB集群初始化测试完成,CDN开始扩容,SLB运维持续排查CPU 100%问题,业务SRE团队协助缩容。
01:18 直播服务流量切换到新的SLB集群,直播服务恢复正常。
01:40 主站、电商、漫画、支付等核心业务逐步切换到新的SLB集群,业务恢复。
01:50 目前,网上服务已基本恢复。
恢复SLB
01:00新的SLB集群搭建完成后,一边切业务止损,SLB运维团队一边开始分析CPU 100%的原因。
01:10 - 01:27 使用Lua程序分析工具跑出详细火焰图数据并进行分析,发现CPU热点明显集中在lua-resty-balancer模块的调用处,从SLB流量入口逻辑到底层模块调用发现此模块中有多个函数可能存在热点。
01:28 - 01:38 选择一个SLB节点,对可能存在热点的函数添加debug日志,并重启,观察这些热点函数的执行结果。
01:39 - 01:58 经过分析debug日志,发现lua-resty-balancer模块中的_gcd函数在某次执行后返回了一个意外值:nan。同时找到了触发条件:某个容器IP的权重为0。
01:59 - 02:06 怀疑是_gcd函数触发了jit编译器的bug,导致运行出错,死循环,导致SLB CPU 100%。临时解决办法:全局禁用jit编译。
02:07 SLB运维修改SLB集群配置,禁用jit编译,批量重启进程,SLB所有CPU恢复正常,可以正常处理请求,同时保留异常站点进程的core文件,以便后续分析。
02:31 – 03:50 SLB运维人员修改了其他SLB集群的配置,并暂时关闭了JIT编译,规避风险。
根本原因定位
11:40分,我们在线下环境成功复现了这个bug,并且发现即使SLB关闭jit编译,这个问题依然存在。此时我们也进一步定位到了这个问题的原因:在服务的一种特殊发布模式下,容器实例的权重会为0。
12:30 经过内部讨论,我们认为问题并未彻底解决,SLB 依然存在很大风险,为了避免问题再次发生,最终决定:平台禁止此发布模式;SLB 优先忽略注册中心返回的权重,强制指定权重。
13:24 此发布模式被发布平台禁止。
14:06SLB修改Lua代码,忽略注册中心返回的权重。
14:30SLB在UAT环境发布升级,多次验证节点权重符合预期,此问题不再出现。
15:00 – 20:00 所有生产SLB集群逐步淘汰并全面升级。
原因
背景
2019年9月,哔哩哔哩从Tengine迁移到OpenResty,基于其丰富的Lua能力,我们开发了服务发现模块,将自研的注册中心的服务注册信息同步到Nginx共享内存中。SLB在转发请求时,通过Lua从共享内存中选择节点处理请求,利用OpenResty的lua-resty-balancer模块。到此次故障发生时,已经稳定运行近两年。
在故障发生前两个月,有业务提出希望通过改变注册中心服务的权重来动态调整SLB的权重,从而实现更精细化的灰度能力。SLB团队评估完这个需求后,认为可以支持,并在开发完成后上线了灰度。
原因
根本原因
问题分析
1、为什么问题刚出现的时候无法登录内网后台?
回顾事件经过,我们发现,当用户登录内网认证系统时,认证系统会跳转到多个域名去植入登录 cookie,其中一个域名被故障的 SLB 代理,由于 SLB 故障,这个域名无法处理请求,导致用户登录失败。流程如下:
随后,我们把办公网络系统的访问链路进行了梳理,与用户链路进行了分离,办公网络链路不再依赖于用户访问链路。
2、为什么故障一开始,多活SLB也不可用?
当多活SLB发生故障时,由于CDN流量回源重试、用户重试等原因,流量突然暴增4倍以上,连接数突然暴增百倍至千万级别,导致这组SLB处于超负荷状态。后来由于流量掉线重启才逐渐恢复。这组SLB集群在每日晚高峰时CPU使用率在30%左右,剩余缓冲不足两倍。如果多活SLB容量足够,理论上可以承载突发流量,多活业务可以立即恢复正常。这里也可以看出,当发生机房级故障时,多活是业务容灾防损最快的解决方案,也是我们在故障之后重点推进的一个方向。
3、为什么SLB变更回滚无效后要选择创建新源站而不是并行运行?
我们 SLB 团队比较小,只有一个平台开发和一个组件运维,当出现故障时,有其他人来协助,但是 SLB 组件的核心变更需要组件运维来执行或者审核,无法并行进行。
4. 为何切换流量到新源站需要这么长时间?
我们的公网架构如下:
这里涉及三支团队:
SLB 应急预案只演练了 SLB 机器初始化、配置初始化,没有与四层 LB 公网 IP 配置、CDN 协同进行全链路演练,也没有对四层 LB Real Server 信息提供、公网运营商线路、CDN 回源 IP 更新等元信息平台进行联动。因此一个完整的新源站需要的时间非常长。事故发生后,这方面的联动和自动化也是我们重点优化的方向。目前一个新集群的创建、初始化、四层 LB 公网 IP 配置可以优化到 5 分钟以内。
5、找到根源之后,证明关闭JIT编译并不能解决问题,那么当晚故障的SLB是如何恢复的呢?
当晚定位到原因是某个容器IP的weight="0",1:45发布应用,weight="0"原因消除,因此关闭JIT虽然无效,但是原因消失,重启SLB后就恢复正常了。
如果此时原因还没有消失,关闭JIT编译后SLB还没有恢复,那么根据定位到的原因信息:某个容器IP的权重为0,还可以定位到该服务以及其发布方式,从而快速定位到根源。
优化与改进
此次事件无论在技术层面还是管理层面都有很多优化和改进,这里我们只列出当时制定的技术面核心优化改进方向。
1. 多主动结构
23:23,已经实现多活的业务核心功能基本恢复正常,如APP推荐、APP播放、评论&弹幕拉取、动态、关注、影视等。直播业务在故障发生时也实现了多活,但当晚未能及时恢复的原因是直播手机首页界面虽然实现了多活,但没有配置多机房调度,导致在主机房SLB不可用的情况下,直播APP首页无法打开,非常可惜。通过这次事故,我们发现了多活架构的一些严重问题:
多活动脚手架容量不足
缺乏业务多活动元数据的平台管理
多个Active/Active切换,容灾能力弱
我们之前的多活切换经常会遇到这样的场景:业务A出现故障,需要切换到多活机房,SRE跟研发沟通确认需要切换域名A+URL A,并通知CDN运营,CDN运营切换完工作负载后,研发发现还有一个URL没有切换,又需要重复上述流程,效率极低,灾备效果很差。
因此我们多元活动建设的主要方向是:
多活动脚手架能力建设
改进的多主动控制能力
2. SLB治理
架构治理
运维能力
自主研发能力
3.故障演练
本次事件中,业务多活流量调度、新源站速度、CDN切量速度、回源超时机制等均未达到预期,因此后续将探索机房级故障演练方案:
4. 紧急响应
B站从来就没有过NOC/技术支持团队,当出现突发事件时,故障响应、故障通报、故障协调等工作都由负责故障处理的SRE同学承担。如果是普通事故还好,如果是重大事故,信息同步根本来不及。因此,必须优化事故应急响应机制:
此次失败的原因是某个服务使用了特殊的发布模式触发的,我们的事件分析平台目前只提供了面向应用的事件查询能力,缺少面向用户、面向平台、面向组件的事件分析能力:
总结
事故发生后,B站瘫痪,迅速成为网上热议话题。作为一名技术人员,我身上的压力可想而知。事故已经发生,我们能做的就是深刻反思,汲取教训,总结经验,砥砺前行。
本文作为“713事故”系列的第一篇,简单介绍了故障的起因、根源、处理以及优化改进等内容。后续文章将详细介绍我们在“713事故”之后是如何实施优化的,敬请期待。
最后我想说一句:多活高可用容灾架构确实是有效的。