“仅相差 8 个字节,整个生产环境竟崩溃了!”

科技   2024-10-15 08:33   山西  
关注我们,设为星标,每天7:40不见不散,架构路上与您共享

回复架构师获取资源


大家好,我是你们的朋友架构君,一个会写代码吟诗的架构师。


在软件开发的世界中,一个看似微不足道的细节往往能够引发连锁反应,最终导致严重的生产问题。本文作者就讲述了一个这样的故事:在一个大型项目中仅因 8 个字节的请求体大小限制,导致整个生产环境崩溃

原文链接:https://hetarth02.hashnode.dev/how-8-bytes-broke-production

作者 | Hetarth Shah       翻译 | 郑丽媛
出品 | CSDN(ID:CSDNnews)

前阵子我接到了一个项目,这个项目属于教育技术领域,许多大公司都在使用,我们姑且称之为“革命性教育知识技术(Revolutionary Education Knowledge Technology)”,简称“REKT”。

关于 REKT 项目,我有许多故事想与大家分享,但还是先从这个故事开始吧:一个关于区区 8 个字节如何导致整个生产环境崩溃的故事。

背景介绍

那是计划进行生产部署的前一天,如果我没记错的话,也是我正在玩的一款游戏进行重大内容更新的前一天。我无法详细介绍项目的实际细节,但可以简单概括一下:你可以把这个项目想象成一个类似于 Udemy(一个在线学习和教学市场)的平台,但它提供的是针对企业的专有领域内容。在 REKT 项目中,我负责实现许多功能,其中之一就是创建一个管理/内容管理面板来管理教育模块——就像在 Udemy 中,一个模块包含许多讲座和内容供用户选择,REKT 也是如此。

明确一点,我并不是这个项目的第一批开发人员。在我之前,有一组开发人员已经搭建了整个“架构”,并为 REKT 选择了技术栈。我认为,掌握基础知识比学习特定语言更为重要,因为对我来说,解决问题的方法过程比知道解决问题的语法更重要。举个简单的例子,如果我需要重复做某件事情,我就会想到用循环。在这个例子中,循环就是解决问题的方法,至于如何具体实现循环,则因不同的编程语言而异。

// For loop in javascriptfor (let i = 0; i < 10; i++) {console.log(i);}
# For loop in pythonfor x in range(0, 10):print(x)
// For loop in PHPfor ($x = 0; $x <= 10; $x++) {echo $x;}

因此,我更注重培养解决问题的思维方式,而不是专注于解决问题的特定语言或语法。

言归正传,当时我对前端、后端和服务器从 MVC 和单体架构的角度有一些了解。幸运的是,我通过 SvelteJs 学到了组件驱动的前端方面知识,不幸的是,我还没机会深入研究 ReactJs 和 VueJs 等框架。你猜猜 REKT 项目的技术栈是什么......前端使用 ReactJs,后端使用 Fastify,并紧密依赖于 AWS 生态系统;最重要的是,这一切都是无服务器的,由 Terraform 进行管理。

而当时,我对无服务器的了解仅仅是:一旦出现请求,它就会启动一个类似服务器的运行时环境。

此外,关于整个架构的构成以及使用了哪些服务的文档非常少,几乎可以说是没有。


部署顺利,开始大胆玩游戏

我不再过多提及过往,快进到功能部署的那一天。我和质量保证团队对这个功能进行了详尽的测试,几乎覆盖了所有可能的情景。一切看起来都很顺利,在得到经理的批准后,我们当天一早就将其推送到生产环境中。部署完成后,质量保证团队开始在实时环境中进行测试。可能是由于过度自信、天真,也可以说是缺乏经验,我毫无顾虑地安装了我正在玩的游戏更新并开始玩了起来。经理也看到了我在玩游戏,但由于一切都很顺利,他也就没太在意。上午的时间进行得非常顺利,生产环境中的所有功能都在正常工作,我们对其进行了多次验证和测试,并告知客户可以开始使用了。

突然搞砸(REKTed)了!

接下来是工作日的后半段。我刚吃完午饭回来,正准备处理其他工单,突然团队聊天里弹出了一条消息:

“保存内容时问题没有添加。” —— 客户

当下,我的脑海中立刻涌上了无数想法:这怎么可能?我们在开发、预发布和生产环境都进行了多次测试,这肯定是个误会。

“可以让他们清除浏览器缓存或强制刷新后再试一次吗?” —— 我

“我们已经在隐身模式下运行了。” —— 客户

我想,这下糟了!我立即打开了开发部署环境并进行检查:我创建了一个课程,添加了一些带有几个问题和选项的内容(测验),点击提交按钮,结果——成功保存了!

我立刻又试了一次,每次都能完美保存。我把我的操作过程录频并发到了团队群里:

“我刚试了一下,它没问题啊。” —— 我

紧接着,客户也发送了一段显示问题的屏幕录制。此时,我和质量保证团队已经在三个不同的环境中逐一尝试了每一种情景,一切都运行得非常好。

时间一分一秒地流逝,尽管我们努力寻找问题所在,但始终没有取得任何突破。为了找出为什么客户无法保存内容的原因,我和质量保证团队甚至还发现了一些其他的重大 Bug。

明明上午都一切顺利,我还有空去玩游戏;但到了那天晚上 11 点,我们都还在找那个 Bug。当时我们太累了,什么都想不起来,就算试着添加一些补丁也都不起作用,我们开始感到绝望。

“我们似乎没有什么进展。今天就到这里吧,明天带着清醒的头脑再来看这个问题。” —— QA

他说得对,我们一整天都在反复做同样的事情,已经陷入了思维定势。

得到资深开发者的帮助

就在我们准备结束这一天的工作时,发生了一件有趣的事情,为我最终解决这一系列问题铺平了道路。一位资深开发者在完成自己的工作后还有一些时间,他主动提出帮助我们调试这个问题。我们尽力总结了当前的情况,但实际上连我们自己都不知道为什么内容无法保存(至于其他 Bug,我和 QA 决定先保密!)。

这位资深开发者愿意加班来帮我们,我们既觉得不好意思,又有些许宽慰。他并没有做出什么特别惊人的举动,只是打开了开发工具,让我输入数据并保存,一切都正常保存。接着,他又让我重现客户遇到的问题,我也欣然照做。

“我觉得问题就在这里……” —— 资深开发者

他向我们展示了两种情况下的请求负载大小:

  • 成功情况下:~8,192 字节

  • 失败情况下:~8,200 字节

“不,这不可能是问题所在。” —— 我

“这肯定不是问题,只不过 8KB 而已,一定还有其他原因。” —— 我再次强调

尽管心里这么想,我们还是决定结束这一天的工作。不过,这个线索给了我们一个新方向去思考第二天该如何解决这个问题。


求求了,下次记得写点文档!

我知道大多数情况下,开发者都不愿意写文档。但至少,请花 5 分钟时间考虑一下未来维护你代码的人吧!你真的希望他们写一篇约 2 千字的文章来抱怨因缺少基本文档而感到无比抓狂吗?

好吧,再次言归正传。第二天早上 7 点左右,我们带着焕然一新的心情早早来到办公室。有一件事让我耿耿于怀,那就是 8KB 的负载大小简直是胡扯(没有对那位资深开发者不敬的意思)。于是我尝试在 fastify 中扩展 POST 主体的大小,重新部署了后端,但同样的问题依然存在。

既然如此,我心想先把这个问题放一放,解决一些其他 Bug,以免它们被客户发现。于是,我暂时搁置了这个问题,转而解决了其他 Bug。虽然这些 Bug 也并不容易解决,但它们并不是完全的黑盒,我可以轻松地追踪代码、找到逻辑中的一个小缺陷。就这样我逐一修复了其他 Bug,虽然主要问题仍未解决,但我终于有了一些希望:有时候,小小的胜利能够改变你的心理状态,调整你的思维方式——对我来说,确实如此。

后来,我又一直在查看前台和后台的错误日志,但没有发现任何错误的迹象。对我来说,这真是一个黑盒,就算我们可以重现 Bug,它也没留下任何可追踪的线索。


换个角度思考

……等等,为什么我没有收到这个特定请求的日志?它明明从前端发出,有时甚至能到达后端。假设 8KB 的问题是对的,这就说明有什么东西阻止了请求到达后端。那会是什么原因呢?我们并没有设置任何服务器...

“我们应该撤销允许所有 CORS 设置的更改,因为那不安全。”——QA

对了!!!安全,安全性,我们是否有针对路由的安全组或任何具有特定规则的东西?我登录 AWS 面板,进入了安全组,但什么也没找到,就连谷歌搜索也没帮上太多忙。然后我突然想到,既然请求没有到达后端,那么肯定有什么东西在保护它。因为是无服务器架构,我认为安全组不太可能是问题所在。那还有什么可能呢?我在谷歌上搜索“AWS 网站安全产品”,然后在传输层/网络层中寻找阻止请求的东西,结果发现它就是这个问题的罪魁祸首......

AWS Web 应用防火墙(WAF)

随后,一切开始变得明朗起来。我搜索了“aws waf 主体大小限制”,并找到了答案。

“我们也使用了 AWS WAF 吗?”—— 我、QA、经理,可能还有客户

不仅我感到意外,整个团队都对此感到惊讶。好在修复这个问题其实非常简单,只需登录 AWS 控制台,更改 WAF 规则以允许更大的请求负载,然后再次测试:终于一切正常了!

不过等我清理了一些代码后重新部署,再次进行了测试……结果又失败了。

什么鬼?!我心想。哦对了,因为整个基础设施是由 Terraform 管理的,所以它重置了 WAF 规则的设置。好吧,暂时先手动更改它,应该就没问题了!至于自动化的问题,就留给未来的我来解决吧。


总结

这一切解决之后,我花了大约一个小时左右的时间,详细记录了整个事件的过程,希望这篇文章可以帮助未来在 REKT 项目中遇到类似问题的任何人。


到此文章就结束了。Java架构师必看一个集公众号、小程序、网站(3合1的文章平台,给您架构路上一臂之力)。如果今天的文章对你在进阶架构师的路上有新的启发和进步,欢迎转发给更多人。欢迎加入架构师社区技术交流群,众多大咖带你进阶架构师,在后台回复“加群”即可入群。



这些年小编给你分享过的干货


0.ChatGPT 4o 国内直接用 !!!

1.idea2024.1.4永久激活码(亲测可用)

2.优质ERP系统带进销存财务生产功能(附源码)

3.优质SpringBoot带工作流管理项目(附源码)

4.最好用的OA系统,拿来即用(附源码)

5.SBoot+Vue外卖系统前后端都有(附源码

6.SBoot+Vue可视化大屏拖拽项目(附源码)


转发在看就是最大的支持❤️

Java架构师必看
致力于分享优质文章及教程【java程序员从初级到中级进阶Java高级架构师】;搜集全网高质量学习书籍面试题视频项目;让您系统提升java架构技术,关注回复『1024』获取Java编程资源,共学习,共进步。
 最新文章