上周,我们团队经历了一次惊心动魄的故障。
故障的起因,是我们深度依赖的AI编程工具Codeium Windsurf出了问题。一个看似普通的代码生成操作,最终导致了生产环境的服务中断了两个多小时,影响了数万用户。
这篇文章就来做一次完整的故障复盘,从故障发生、排查、应急处理到事后复盘,聊聊整个过程,以及我们从中学到的教训。
背景介绍
先简单介绍一下背景。
Codeium Windsurf是Codeium推出的AI编程IDE,基于VS Code,内置了强大的AI代码生成和重构功能。我们团队从2024年初开始使用Windsurf,主要用它来做代码补全、代码生成、代码重构、代码解释等。
用了几个月,大家都觉得很好用,开发效率提升了不少。特别是对于一些重复性的代码(比如CRUD接口、数据转换、单元测试),Windsurf能快速生成,节省了很多时间。
我们团队有一条不成文的规定:AI生成的代码,必须经过人工review才能提交。但随着使用时间变长,大家对AI生成的代码越来越信任,review的严格程度也在下降。有时候,一些看起来简单的代码,就直接提交了。
这次故障,就是在这样的背景下发生的。
故障发生
故障发生在周三下午两点多。
当时,一个同事正在开发一个新功能,需要写一个数据导出的接口。他用Windsurf生成了一段代码,功能是从数据库查询数据,然后导出成Excel文件。
这段代码看起来很正常:接收参数、查询数据库、生成Excel、返回文件。同事review了一下,觉得没什么问题,就提交了代码,合并到了主分支。
我们的CI/CD流水线是自动的,代码合并到主分支之后,会自动构建、自动部署到生产环境。下午两点半,新版本部署上线。
部署之后,刚开始一切正常。但过了大约十分钟,监控系统开始报警:数据库连接数飙升,CPU使用率超过90%,接口响应时间从原来的200毫秒变成了5秒以上。
紧接着,用户开始反馈:系统打不开,操作卡顿,导出功能用不了。我们的客服群里,消息一条接一条地弹出来。
那一刻,我们意识到:出大事了。
排查过程
接到报警之后,我们立刻开始排查。
第一步是看监控。监控显示,数据库的连接数已经达到了上限(500个连接),大部分连接都在执行一个查询,而且查询时间很长,有的已经执行了几分钟还没结束。CPU使用率95%,内存使用率85%,数据库已经濒临崩溃。
第二步是看慢查询日志。我们在慢查询日志里找到了那个耗时很长的SQL。一看就发现了问题:这个SQL没有分页,也没有时间范围限制,是一个全表扫描。表里面有两千多万条数据,全表扫描一次,要好几分钟,而且会占用大量的数据库资源。
第三步是定位代码。我们根据SQL的特征,找到了对应的代码。就是那个同事刚提交的数据导出接口。代码里的查询逻辑是这样的:根据用户传入的参数,查询符合条件的所有数据,然后全部导出来。如果用户不传时间范围,就查询全部数据。
问题就出在这里。Windsurf生成的代码,没有做参数校验,也没有做分页限制。用户如果不传时间范围,就会查询全表。而这个接口上线之后,正好有几个用户在使用,其中一个用户没有传时间范围,触发了全表扫描。
更严重的是,这个查询很慢,占用了数据库连接。其他用户的请求也在等待数据库连接,导致连接池被占满,整个系统的所有接口都变慢了,甚至超时。
第四步是确认影响范围。我们确认,这个故障影响了所有依赖这个数据库的服务,包括主站、APP、后台管理系统,全部受影响。用户无法登录、无法下单、无法查询数据,整个系统基本瘫痪。
从发现报警到定位到问题,我们用了大约15分钟。
应急处理
定位到问题之后,我们立刻开始应急处理。
第一步是回滚。我们立刻回滚了刚刚部署的版本,把有问题的代码撤下来。回滚操作很快,两分钟就完成了。
但回滚之后,数据库的压力并没有立刻降下来。因为那些已经在执行的慢查询还在跑,数据库连接还被占着。
第二步是杀掉慢查询。我们连接到数据库,手动杀掉了那些执行时间超过一分钟的查询。杀了几十个查询之后,数据库连接数开始下降,CPU使用率也开始回落。
第三步是验证服务恢复。杀掉慢查询之后,接口响应时间开始恢复正常,监控指标逐渐回到正常水平。我们测试了几个核心功能,确认可以正常使用。
第四步是通知用户。我们通过APP推送、短信、官网公告等方式,通知用户系统已经恢复,对受影响的用户表示歉意,并承诺会进行补偿。
从故障发生到服务完全恢复,一共用了两个多小时。这两个小时,对于我们团队来说,是惊心动魄的两个小时。
深入分析:为什么会发生
服务恢复之后,我们没有急着总结,而是先做了深入的分析,搞清楚为什么会发生这样的故障。
直接原因很明显:AI生成的代码有缺陷,没有做参数校验和分页限制,导致全表扫描,拖垮了数据库。
但深入分析,我们发现了更多的问题。
第一个问题:代码review流于形式。按照规定,AI生成的代码必须经过人工review。但实际操作中,同事review的时候,只看了代码的逻辑是否正确,没有关注性能和安全方面的问题。他觉得这是一个简单的导出接口,不会有什么大问题,就放松了警惕。
第二个问题:CI/CD缺少自动化检查。我们的CI流水线,只做了代码编译和单元测试,没有做代码质量检查、安全扫描、性能检查。如果有自动化的SQL检查工具,能在代码提交的时候就发现这个全表扫描的问题,就不会部署到生产环境了。
第三个问题:数据库缺少防护。我们的数据库没有设置查询超时时间,也没有限制单个查询的资源使用。一个慢查询,可以无限期地占用数据库连接,直到把数据库拖垮。如果设置了查询超时(比如30秒),慢查询会被自动杀掉,不会造成这么大的影响。
第四个问题:对AI工具过度信任。用了几个月Windsurf之后,团队对AI生成的代码越来越信任,觉得AI生成的代码应该没什么问题。这种过度信任,导致了review的松懈,也导致了风险意识的下降。
第五个问题:灰度发布缺失。我们的部署是全量发布,新版本一上线就面向所有用户。如果有灰度发布机制,先发布给一小部分用户,发现问题之后及时回滚,影响范围就会小很多。
这些问题,单独看可能都不是大问题,但凑在一起,就导致了这次故障。
Windsurf本身的问题
除了我们自身的问题,我们也分析了Windsurf这个工具本身的问题。
第一个问题:AI生成的代码,倾向于"能跑就行",不考虑边界情况和性能。Windsurf生成的导出接口,功能上是正确的,但它没有考虑数据量很大的情况,没有做分页,没有做参数校验。这是AI生成代码的一个普遍问题:它关注的是"功能正确",而不是"生产可用"。
第二个问题:AI生成的代码,可能引入安全漏洞。比如SQL注入、XSS、权限绕过等。虽然这次故障不是安全问题,但如果不注意,AI生成的代码很容易引入安全漏洞。
第三个问题:AI工具的稳定性。故障发生的当天,Windsurf本身也有一些不稳定,有时候代码生成会超时或者出错。虽然这不是故障的直接原因,但AI工具的稳定性,也是需要考虑的风险。
第四个问题:AI工具的更新可能引入新问题。Windsurf会自动更新模型和功能,有时候更新之后,生成代码的风格和质量会发生变化。如果没有注意到这些变化,可能会引入新的问题。
我们不是要否定Windsurf这个工具,它确实很好用,也确实提升了开发效率。但我们需要认识到,AI工具不是银弹,它有自己的局限性和风险。
改进措施
分析完原因之后,我们制定了一系列改进措施。
第一,严格代码review制度。AI生成的代码,必须经过至少两个人的review,而且review不能只看功能,还要看性能、安全、边界情况。review人要对代码质量负责,如果review过的代码出了问题,review人也要承担责任。
第二,增加CI自动化检查。在CI流水线里,增加了代码质量检查(SonarQube)、安全扫描(Snyk)、SQL检查(检查全表扫描、缺少索引等)。这些检查不通过,代码不能合并。
第三,加强数据库防护。给数据库设置了查询超时时间(30秒),限制了单个用户的最大连接数,增加了慢查询告警。同时,对所有的查询接口,都要求必须有分页或者时间范围限制。
第四,建立AI代码使用规范。制定了《AI编程工具使用规范》,明确了哪些代码可以用AI生成,哪些必须手写;AI生成的代码必须经过哪些检查;如何评估AI生成代码的质量。同时,定期组织AI代码风险的培训,提高大家的风险意识。
第五,引入灰度发布。把全量发布改成了灰度发布,新版本先发布给10%的用户,观察30分钟没有问题,再逐步扩大到全量。如果发现问题,可以快速回滚,影响范围很小。
第六,完善应急预案。完善了故障应急预案,明确了故障发生后的处理流程、责任人、沟通机制。同时,定期进行故障演练,提高团队的应急响应能力。
这些改进措施,我们在故障之后的两周内全部落地了。
经验和教训
这次故障,给我们团队上了深刻的一课。总结一下经验和教训。
第一,AI生成的代码,必须和手写代码一样严格对待,甚至要更严格。因为AI生成的代码,看起来很正确,但可能隐藏着你想不到的问题。不要因为是AI生成的,就放松了review和测试。
第二,工具是辅助,人是主导。AI编程工具能提升效率,但不能替代人的判断和责任。最终,代码的质量和系统的稳定性,还是要靠人来保障。
第三,不要过度依赖任何工具。不管是AI编程工具,还是其他第三方服务,都要有备选方案和风险预案。工具出问题的时候,不能影响核心业务。
第四,自动化检查很重要。光靠人来review,难免有疏漏。用自动化工具做代码质量、安全、性能的检查,能发现很多人发现不了的问题,而且成本很低。
第五,故障不可怕,可怕的是不总结。每次故障,都是一次学习和改进的机会。认真复盘,找到根本原因,制定改进措施,并且真正落地,才能避免同样的故障再次发生。
第六,灰度发布和回滚机制是生产环境的标配。不管你对代码多有信心,都不要全量发布。灰度发布能把故障的影响降到最低,快速回滚能缩短故障时间。
写在最后
这次Windsurf故障,是我们团队使用AI编程工具以来,最严重的一次事故。两个多小时的服务中断,数万用户受影响,这个教训很深刻。
但我想说的是,我们不会因为这次故障就放弃使用AI编程工具。AI工具确实能提升效率,这是不可否认的。我们要做的,是在享受AI带来的便利的同时,建立完善的风险防控机制,把AI的风险控制在可接受的范围内。
AI时代已经到来,我们不可能回到没有AI的时代。但如何正确地使用AI,如何在效率和安全之间找到平衡,是每个团队都需要思考的问题。
希望我们的这次故障复盘,能给正在使用或者打算使用AI编程工具的团队一些参考和警示。AI很好用,但请保持警惕。
最后,向受这次故障影响的用户,再次表示诚挚的歉意。我们会继续努力,把系统做得更稳定、更可靠。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录