7行代码让B站崩溃3小时竟因“一个诡计多端的0”
发布于 2023-09-21 12:53:28 阅读()作者:147小编
已有9352成功领取POS机
7行代码让B站崩溃3小时竟因“一个诡计多端的0”
鱼羊丰色发自凹非寺量子位|公众号QbitAI
一个小小字符“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,函数中:
ifb==0thenreturnaend
这个判断语句生效,结果就算出来了。
基于这样的数学原理,我们再来看这段代码,似乎没什么问题:
但如果输入的b是个字符串“0”呢?
B站的技术解析文章中提到,这段出事的代码是用Lua写的。Lua具有这么几个特点:
这是一种动态类型语言,常用习惯里变量不需要定义类型,直接给变量赋值就行。Lua在对一个数字字符串进行算术操作时,会尝试将这个数字字符串转成一个数字。在Lua语言中,数**算n%0的结果是nan-NotANumber-。
我们来模拟一下这个过程:
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模块用于选择upstreamserver,在节点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,运行出错陷入死循环导致SLBCPU100%。
于是就全局关闭了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
B站进入界面刷不出来是怎么回事,以为是网络不好,换了几个地方也刷不出来是怎么回事?
服务器崩溃。
2021年7月13日晚,众多用户反映B站网页端和移动端均出现加载失败的现象。“b站崩了”也冲上热搜第一。B站回应称:部分服务器机房发生故障,造成无法访问。技术团队随即进行了问题排查和修复,现在服务已经陆续恢复正常。
7月14日,据哔哩哔哩弹幕网消息,B站发布消息对B站崩溃表示抱歉,并表示将会赠送所有用户1天大会员。
7月15日,不少粉丝发现昨日(7月14日)B站赠送的大会员或电视大会员发生了自动续费的情况。而此次会员赠送,是B站为APP和网页“宕机”的补偿。
B站崩溃3小时引网友狂欢
“B站崩了”的话题仅用了不到半小时就冲上了微博的热搜头条,随后知乎、豆瓣等网络社区的讨论度和热度也是直线上升,一度让微博陷入卡顿,知乎、豆瓣等社区加载缓慢。
更有意思的是,“B站崩溃”事发时已经是晚上11点,常理来说应该有不少人已经进入了梦乡,网站的访问量相比起八九点的高峰期应该已经下降了许多。
即使如此关于B站的消息依然迅速引起了全网热议,甚至一度有传言称B站崩溃后,四散的用户甚至带崩了A站、豆瓣和知乎等网络社区网站的服务器。
以至于网友调侃:B站的服务器一崩,加班的除了B站程序员还包括A站、知乎、豆瓣、微博等网站的程序员,建议以后重点盯防B站,B站一旦崩溃马上开启备用服务器分流即将到来的流量。
b站崩溃真实原因
因为服务器不稳定造成的。
日前,“B站”相关话题冲上热搜榜第一名。原来,不少网友反映,哔哩哔哩**无法正常观看。这令一众网友颇为吃惊,在话题评论区,他们各抒己见,大部分人都没想到,“浓眉大眼”的B站也能崩,还怀疑自家网络或手机出问题了。B站“崩”上热搜背后,一个数据值得关注。2022年四季度,B站月均活跃用户达3.26亿,同比增长20%。这无疑说明了B站当前的热度,不过,对B站管理层来说,实现盈利仍是头等大事。
B站“崩”上热搜,令一众网友还是深感吃惊。他们在话题评论区各抒己见:“还以为自己WiFi抽风了”“把路由器重启了八次”“还以为是我手机崩了”。其实,这并非B站第一次出现崩溃的情况。早在2021年7月,B站就出现过比较大规模的服务器崩溃。当时,B站方面表示,新上线的代码函数存在问题,才导致服务器出现了故障。J*A中文是什么意思
J*A中文意思是:计算机编程语言。
J*a是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此J*a语言具有功能***大和简单易用两个特征。J*a语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
任职于太阳微系统的詹姆斯·高斯林等人于1990年代初开发J*a语言的雏形,最初被命名为Oak,目标设置在家用电器等小型系统的编程语言,应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。
由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项**。随着1990年代互联网的发展,Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以J*a的名称正式发布。J*a伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。
扩展资料:
J*A和互联网的渊源:
1994年6月,在同约翰·盖吉、詹姆斯·高斯林、比尔·乔伊、帕特里克·诺顿、韦恩·罗斯因和埃里克·施密特经历了一场历时三天的头脑风暴后,团队决定再一次改变努力的目标,这次他们决定将该技术应用于万维网。
他们认为随着Mosaic浏览器的到来,因特网正在向同样的高度互动的远景演变,而这一远景正是他们在有线电视网中看到的。作为原型,帕特里克·诺顿写了一个小型万维网浏览器,WebRunner,后来改名为HotJ*a[12]。
1994年10月,HotJ*a和J*a平台为公司高层进行演示。1994年,J*a 1.0a版本已经可以提供下载,但是J*a和HotJ*a浏览器的第一次公开发布却是在1995年3月23日SunWorld大会上进行的。升阳公司的科学指导约翰·盖吉宣告J*a技术。
这个发布是与网景公司的执行副总裁马克·安德森的惊人发布一起进行的,宣布网景将在其浏览器中包含对J*a的支持。1996年1月,Sun公司成立了J*a业务集团,专门开发J*a技术。
参考资料来源:百度百科-J*a
相关文章推荐
-
银盛通pos机官方热线() 09-03
-
银盛通pos机办理流程() 09-23
-
银盛通pos机无法刷卡(银盛通突然刷不了卡) 09-21
-
银盛通pos机申请平台() 08-31
-
银盛通pos机如何操作() 09-07
-
银盛通pos机点了消费() 09-03
-
银联盛付通pos机() 09-05
-
银盛通pos机不签名() 09-01
-
银盛通pos机怎么查询() 09-11
-
盛瑞传动党委组织参观潍坊市党性教育基地 09-07
-
突然集体涨价网友住不起了 09-09
-
45岁开始交社保缴费15年需要二三十万元划算吗 09-19