发布于 2026-01-06 8 阅读
0

这不是一个令人愉快的开发故事,而是一个关于升级的故事。

这不是一个令人愉快的开发故事,而是一个关于升级的故事。

要一直保持积极乐观很难,工作生活比博客文章或试图从零开始教你走向成功的 YouTube 教程要复杂得多,工作生活比大多数网红在视频中向我们展示的要困难得多,痛苦也更多。

今天,我们不得不再次撤销团队几个月来的工作成果。这项工作凝聚了开发人员、质量保证人员、项目经理以及组织内其他领导者数小时的心血。我们喜欢认为自己拥有一个宏伟的庞然大物,就像 @DHH 形容他的电子邮件服务 Hey 那样,但是,我们也知道我们并没有那么宏伟,因为它是由人创造的,并且还有技术债务需要偿还。

我想给你们讲讲这个故事,这是我们团队的故事。如果他们读了这篇文章,就能知道故事里每个人都是谁。我只知道,在这个任务中,他们每个人都同样重要。这项任务目前看起来可能像是失败了,但我们通过反复部署和撤回,从中吸取了更多经验教训。

这一切始于几个月前,当时我们内部决定升级我们的Web框架。之前为了专注于功能开发,我们一直推迟这项工作,但现在我们认为是时候偿还这笔技术债务了。整个开发团队一直在为我们的仓库添加自动化测试,包括单元测试、功能测试和Selenium测试,我们每周都在增加测试的数量。

我们把升级准备工作的任务分配给了我们团队的一位“忍者”开发人员——是的,我们有好几个这样的“忍者”——他的唯一工作就是移除我们对旧库的手动依赖,并确保我们的产品仍然能够正常运行。这听起来容易吗?一点也不……他为此投入了数小时、数天甚至数月的时间,每次他觉得快要完成的时候,就会发现新的产品问题,然后他不得不去解决。他就像一个孤军奋战的乐手,虽然我们团队整体运作良好,但他的任务是帮助我们升级到下一个版本,这绝非易事。

尝试 1

经过数周的努力,他终于准备好了他的分支(这里指的是 Git),供我们的质量保证团队使用。他们开始从里到外、从上到下地检查代码中的错误或问题,这就是他们的工作。他们开始在应用程序中发布意外行为的问题,然后是其他不一致之处,所有这些都被记录在这个“超级 Jira 问题”中。

他担心自己破坏了系统的重要部分,甚至担心自己的名誉,有些问题确实是他造成的,但有些问题却是我们忘记了的存在,这些问题存在于使用率低的模块中,或者存在于本来就不应该运行的罕见场景中。

所有这些经验教训,反而让团队更加担忧正在计划的工作。领导们不得不召开会议,逐个审查,评估这项工作的关键性,甚至考虑是否应该开展。

经过商议,我们决定继续推进,将其部署到生产环境。此时,开发人员、测试人员、技术主管、经理等已经为此投入了数小时的时间。因此,我们对这个方案充满信心。

我们计划在周末进行这项操作,我们不想造成任何产品中断,时机已到,那天是星期六,所以……我们(团队)部署到生产环境!

最初几分钟的监控进行得很顺利,但几分钟后,QA 团队注意到以前永不过期的会话开始过期,他们认为这与别的问题有关……经过数小时的测试,我们将版本标记为稳定,并度过了一个愉快的周末。

星期一早上,我们收到了第一批用户的投诉,他们抱怨说他们的会话过期了,无法完成他们在系统中尝试完成的课程,支持人员也无法完成任务,因为系统会将他们注销。

我们一直在探究这一切发生的原因,找出差异所在。如果生产环境和开发环境理应完全相同,我们怎么会忽略这个问题呢?究竟是什么不同之处……

上午 11 点,我们决定撤回之前的决定,我们坚持了大约 4 个小时,通过电话和电子邮件处理工单,最终放弃了几个月的工作成果。

问题出在哪里?我们发现数据库团队发现会话表存在性能问题,需要添加索引和一个合并字段。然而,我们从未在开发环境中实施这项更改,为什么?因为我们认为这无关紧要。开发环境的技术主管为什么没有考虑到这一点?他认为这无关紧要……这完全是一系列想当然的结果。

暂停项目

我们内部还有其他优先事项,那位技术高超的开发人员正在将 Bitbucket 迁移到 Github,并实施 Jenkins 来停止使用现在非常昂贵的 Bitbucket Pipelines,这是一个节约成本的问题。在疫情期间,我们可以再拖延几周,以偿还这笔技术债务。

开发人员很沮丧,因为他花了几个月的时间所做的工作被撤销了,所有团队都继续推进项目。他有时受到祝贺,但他知道自己还没有完成这个项目,所以他继续在业余时间研究,找出会话问题,最终我们的数据库团队撤销了这个问题。

失败之后,一些团队对该项目进行了更加严格的审查,讨论了返工量、返工成本、返工是否值得、开发人员是忍者还是普通人等等。

他和他的搭档决定再试一次。

关于项目参与

他们又把这个项目拿给我了,顺便说一下,我是能源部的,我决定再次参与,这次采取不同的策略。我们不会等到周末,而是会在早上 5 点进行部署,赶在主要在办公时间工作的客户登录之前。我们会快速测试已知问题、会话持续时间、系统加载时间等等。如果一切正常,我们就让升级稳定下来,然后再继续添加我们正在开发的新功能和错误修复。

我决定早上 4:45 起床,洗个澡,喷点香水,穿上衬衫,让自己看起来像是已经准备好参加早上的视频会议了。

团队部署完毕并开始测试,这感觉就像发射火箭一样,每个人都在线上,监控服务,甚至在空闲时间还讲笑话。

早上 7 点,我们开始有客户了,一切看起来都很正常。我在推特上发文庆祝这一成果,并赞扬团队在周五早上打破行业内“周五不部署”规则的勇气。

下午5点,我们结束了一天的工作,一切看起来都很正常。但我们开始发现一个与此版本中新增的垃圾回收流程相关的问题,数据库进程开始堆积,我们注意到处理这些进程的查询语句发生了变化,于是我们与数据库团队联系,提出了一些性能优化建议……

下午6点,我们决定让我们的“忍者”开发人员利用周末时间开发一个补丁,将最新版本的改进移植到这个仍然有两年历史的版本中。我们只做一些小的改进,以确保不会破坏现有功能。而他做到了。

周一

我们开始收到数据库警报,问题接踵而至,我们不得不开始手动终止进程。

该补丁的拉取请求已获批准并部署到沙盒环境,QA 团队迅速投入测试,而与此同时,我们的生产服务器却不堪重负,响应时间比平时要长。

补丁通过了QA团队的审核,我们准备部署,但是……我们犹豫了。我们的CTO开始询问后果,并提醒我们,在紧急情况下操之过急并不值得,升级前我们的产品已经很稳定了,所以目前应该维持现状。

我个人觉得这不是个正确的决定,我们当时已经掌握了补丁,但我知道他是对的,这是一个很大的补丁,后果可能比我们目前经历的这段低迷时期还要严重。

周一下午 6 点,回滚操作完成,升级已从生产环境中移除,现在,我们将着手进行下一次尝试,以实现这一目标。

团队始终没有放弃。当我们在其他论坛上讨论这些问题时,人们纷纷告诉我们哪些事情我们可以避免,哪些事情我们可以做得更好。我们知道这些,但我们也知道,我们会从每一次经验中学习,避免重蹈覆辙。

正如那句流行语所说:

那些杀不死你的,只会让你更强大。

文章来源:https://dev.to/marianorenteria/this-is-not-a-happy-dev-story-about-an-upgrade-3mfb