> 首页 > 科技 > 互联网 > 7 行代码让B站崩溃 3 小时,竟因“一个诡计多端的 0”

7 行代码让B站崩溃 3 小时,竟因“一个诡计多端的 0”

来源:本站 作者:佚名 时间:03-28 手机版

感谢小编网友 Sancu 的线索投递!

一个小小字符“0”,竟引得B站全面崩溃。

不知你是否还记得那一夜,B站“大楼停电”“服务器爆炸”“程序员删库跑路”的彻夜狂欢。(手动狗头)

时隔一年,背后“真凶”现在终于被阿 B 披露出来 ——

没想到吧,就是这么简单几行代码,直接干趴B站两三个小时,搞得B站程序员彻夜无眠头发狂掉。

你可能会问,这不就是个普普通通用来求最大公约数的函数吗,怎么就有如此大的威力?背后一桩桩一件件,归根结底其实就一句话:0,它真的不兴除啊。

具体详情,咱们还是一起来看看“事故报告”。

字符串“0”引发的“血案”

先来说道说道引发惨案的根本原因,也就是开头贴出的这个 gcd 函数。学过一点编程知识的小伙伴应该都知道,这是一种用辗转相除法来计算最大公约数的递归函数。

跟我们手算最大公约数的方法不同,这个算法是这样的:

举个简单的例子,a=24,b=18,求 a 和 b 的最大公约数;

a 除以 b,得到的余数是 6,那么就让 a=18,b=6,然后接着往下算;

18 除以 6,这回余数是 0,那么 6 也就是 24 和 18 的最大公约数了。

也就是说,a 和 b 反复相除取余数,直到 b=0,函数中:

if b==0 then return a end

这个判断语句生效,结果就算出来了。基于这样的数学原理,我们再来看这段代码,似乎没什么问题:

但如果输入的 b 是个字符串“0”呢?

B站的技术解析文章中提到,这段出事的代码是用 Lua 写的。Lua 具有这么几个特点:

这是一种动态类型语言,常用习惯里变量不需要定义类型,直接给变量赋值就行。Lua 在对一个数字字符串进行算术操作时,会尝试将这个数字字符串转成一个数字。在 Lua 语言中,数学运算 n%0 的结果是 nan (Not A Number)。

我们来模拟一下这个过程:

1、当 b 是一个字符串“0”时,由于这个 gcd 函数没有对其进行类型校验,因此在碰上判定语句时,“0”不等于 0,代码中“return _gcd (b, a% b)”触发,返回_gcd (“0”, nan)。

2、_gcd (“0”, nan) 再次被执行,于是返回值变成了_gcd (nan, nan)。

这下就完犊子了,判定语句中 b=0 的条件永远没法达到,于是,死循环出现了。也就是说,这个程序开始疯狂地原地转圈,并且为了一个永远得不到的结果,把 CPU 占了个 100%,别的用户请求自然就处理不了了。

那么问题来了,这个“0”它到底是怎么进去的呢?

官方说法是:

在某种发布模式中,应用的实例权重会短暂地调整为 0,此时注册中心返回给 SLB(负载均衡)的权重是字符串类型的“0”。此发布环境只有生产环境会用到,同时使用的频率极低,在 SLB 前期灰度过程中未触发此问题。SLB 在 balance_by_lua 阶段,会将共享内存中保存的服务 IP、Port、Weight 作为参数传给 lua-resty-balancer 模块用于选择 upstream server,在节点 weight=“0”时,balancer 模块中的_gcd 函数收到的入参 b 可能为“0”。

bug 是如何定位的

以“事后诸葛亮”的视角来看,这个引发B站全面崩溃的根本原因多少有点让人直呼“就这”。但从当事程序员的视角来看,事情确实没有辣么简单。

当天晚上 22:52 分 —— 大部分程序员才刚下班或者还没下班的节骨眼(doge),B站运维收到服务不可用的报警,第一时间怀疑机房、网络、四层 LB、七层 SLB 等基础设施出现问题。

然后立马和相关技术人员拉了个紧急语音会议开始处理。5 分钟后,运维发现承载全部在线业务的主机房七层 SLB 的 CPU 占用率达到了 100%,无法处理用户请求,排除其他设施后,锁定故障为该层。

(七层 SLB 是指基于 URL 等应用层信息的负载均衡。负载均衡通过算法把客户请求分配到服务器集群,从而减少服务器压力。)

万般紧急之时,小插曲还现了:远程在家的程序员没法进入内网,只好又去 call 了一遍内网负责人,走了个绿色通道才全部上线(因为其中一个域名是由故障的 SLB 代理的)。

此时已经过去了 25 分钟,抢修正式开始。

首先,运维先热重启了一遍 SLB,未恢复;然后尝试拒绝用户流量冷重启 SLB,CPU 依然 100%,还是未恢复。

接着,运维发现多活机房 SLB 请求大量超时,但 CPU 未过载,正准备重启多活机房 SLB 时,内部群反应主站服务已恢复,视频播放、推荐、评论、动态等功能已基本正常。

此时是 23 点 23 分,距离事故发生 31 分钟。

值得一提的是,这些功能恢复其实是事发之时被网友们吐槽的“高可用容灾架构”发挥了作用。

至于这道防线为啥一开始没发挥作用,里头可能还有你我一点锅。

简单来说,就是大家伙点不开B站就开始疯狂刷新,CDN 流量回源重试 + 用户重试,直接让B站流量突增 4 倍以上,连接数突增 100 倍到千万级别,多活 SLB 就给整过载了。

不过,并不是所有服务都搞了多活架构,至此事情并没完全解决。接下来的半个小时里,大家做了很多操作,回滚了最近两周左右上线的 Lua 代码,都没把剩余的服务恢复。

时间来到了 12 点,没有办法了,“先不管 bug 是怎么出来的,把服务全恢复了再说”。简单 + 粗暴:运维直接耗时一小时重建了一组全新的 SLB 集群。

凌晨 1 点,新集群终于建好:一边,有人负责陆续将直播、电商、漫画、支付等核心业务流量切换到新集群,恢复全部服务(凌晨 1 点 50 分全部搞定,暂时结束了崩了逼近 3 个小时的事故);

另一边,继续分析 bug 原因。在他们用分析工具跑出一份详细的火焰图数据后,那个搞事的“0”才终于露出了一点端倪:CPU 热点明显集中在一个对 lua-resty-balancer 模块的调用中。而该模块的_gcd 函数在某次执行后返回了一个预期外的值:NaN。

同时,他们也发现了触发诱因的条件:某个容器 IP 的 weight=0。他们怀疑是该函数触发了 jit 编译器的某个 bug,运行出错陷入死循环导致 SLB CPU 100%。于是就全局关闭了 jit 编译,暂时规避了风险。一切都解决完后,已经快 4 点,大家终于暂时睡了个好觉。

第二天大家也没闲着,马不停蹄地在线下环境复现了 bug 后,发现并不是 jit 编译器的问题,而是服务的某种特殊发布模式会出现容器实例权重为 0 的情况,而这个 0 是个字符串形式。

正如前面所说,这个字符串“0”在动态语言 Lua 中的算术操作中,被转成了数字,走到了不该走的分支,造成了死循环,引发了 b 站此次前所未见的大崩溃事件。

递归的锅还是弱类型语言的锅?

不少网友都还对这次事故记忆犹新,有回想起自己就是以为手机不行换电脑也不行的,也有人还记得当时 5 分钟后此事就上了热搜。

大家都很诧异,就这么一个简单的死循环就能造成如此大的网站崩服。不过,有人指出,死循环不罕见,罕见的是在 SLB 层、在分发过程出问题,它还不像在后台出问题很快能重启解决。

为了避免这种情况发生,有人认为要慎用递归,硬要用还是设置一个计数器,达到一个业务不太可能达到的值后直接 return 掉。

还有人认为这不怪递归,主要还是弱类型语言的锅。以此还导致了“诡计多端的‘0’”这一打趣的说法。

另外,由于事故实在是耽误了太久、太多事儿,当时B站给所有用户补了一天大会员。

有人就在此算了一笔账,称就是这 7 行代码,让 b 站老板一下亏了大约 1,5750,0000 元。(手动狗头)

对于这个 bug,你有什么想吐槽的?

参考链接:

[1]《2021.07.13 我们是这样崩的》by 哔哩哔哩技术

https://mp.weixin.qq.com/s/nGtC5lBX_Iaj57HIdXq3Qg

相关推荐:

win74g内存虚拟内存设置多少合适-win74g内存虚拟内存设置教程

7 行代码让B站崩溃 3 小时,竟因“一个诡计多端的 0”

win7系统资源管理器停止工作怎么解决?

应对苹果 iPhone 14 量产,富士康深圳厂招工奖金提高逾两成

修复Win7 Aero效果主题无法显示的教程

华人科学家发现迄今为止“最佳半导体材料”

win7出现多个网络连接?win7电脑多个本地连接解决办法

环球晶:8 寸、12 寸硅晶圆需求健康,6 寸产能松动

标签: [db:标签]

声明:《7 行代码让B站崩溃 3 小时,竟因“一个诡计多端的 0”》一文由排行榜大全(佚名 )网友供稿,版权归原作者本人所有,转载请注明出处。如果您对文章有异议,可在反馈入口提交处理!

最近更新

  • win74g内存虚拟内存设置多少合适-win74g内存虚拟内存设置教程

    win74g内存虚拟内存设置多少合适-win74g内存虚拟内存设置教程?当我们使用计算机时,我们经常会遇到内存不足的问题,特别是当我们玩大型游戏时。...

    互联网 日期:2023-03-28

  • 如何提高网速

    1、首先第一种办法,每天在电脑关机前都清理一下磁盘,大家找到C盘,然后右键点击选择属性”,然后找到磁盘清理选项就好了,每天清理一遍有很多好处。...

    百科 日期:2023-03-28

  • 如何迎接高考

    应对方式:一、是摆正心态。认真对待高考,它是人生的一个重要台阶,能进入心仪的学校,无论从实现个人的愿望,还是对个人今后的发展都至关重要,于此...

    百科 日期:2023-03-28

  • 7 行代码让B站崩溃 3 小时,竟因“一个诡计多端的 0”

    感谢小编网友 Sancu 的线索投递!一个小小字符“0”,竟引得B站全面崩溃。不知你是否还记得那一夜,B站“大楼停电”“服务器爆炸”“程序员删库跑...

    互联网 日期:2023-03-28

  • 莫斯科的历史

    莫斯科是一座历史悠久的城市,作为居民点最早见诸史册是在公元1147年。1812年拿破仑率领的法军占领莫斯科后,这个城市在大火中焚毁,但很快又重新...

    百科 日期:2023-03-28

  • win7系统资源管理器停止工作怎么解决?

    win7资源管理器停止工作是一个非常棘手的问题。虽然这不是一个很麻烦的问题,但也需要一些时间。若要了解如何解决此问题,请参阅以下详细信息。...

    互联网 日期:2023-03-28

  • 应对苹果 iPhone 14 量产,富士康深圳厂招工奖金提高逾两成

    感谢小编网友 娃哈哈纯净水 的线索投递!小编 7 月 24 日消息,据中证报报道,富士康深圳龙华厂区为了应对苹果 iPhone 14 的量产工作需求,将 iPho...

    互联网 日期:2023-03-28

  • 如何迎合别人

    1、为观点看法找事实,当听到对方话语中的观点看法时,要补充一个相关的事实,从而迎合对方,对方的观点更加有说服力。2、为事实找观点看法,在交谈中...

    百科 日期:2023-03-28

邮箱不能为空
留下您的宝贵意见