写点什么

事故复盘:我们是怎么弄丢 1400 万条日志记录的

  • 2019-11-28
  • 本文字数:3637 字

    阅读完需:约 12 分钟

事故复盘:我们是怎么弄丢1400万条日志记录的

在这里,我们就将涉事企业姑且称为“某公司”。至于发现问题的开发人员,我们也隐去真名,称其为王二。


在本文中,我们借此机会聊聊软件开发中的人为错误,以及针对这些错误应当采取的预防措施。

从开发到生产

首先某公司部署代码库变更的基本流程总结如下:


  1. 开发人员测试变更内容(属于流程中的常识性步骤,因此不做强调)。

  2. 代码审查(仅需要一名审查员,用于审查的时间一般也不长)。

  3. 将代码 push 至预生产环境。测试预生产环境。

  4. 在 push 至生产环境前重新审查变更清单。

  5. 在 push 至生产环境过程中重新审查变更清单。

  6. 在 push 至生产环境之后重新审查变更清单。


飞行员起飞前的检查清单列表里有一句话:


测试标准实践明确指出,飞行员必须妥善记录变更清单。


毫无疑问,飞行员在起飞之前当然得对飞机进行一番全面检查,这是毋庸争论的事实。如果飞行员没有负起检查责任,或者机场工作人员坦言为了避免晚点,检查过程中省略了某些步骤,乘客怎么敢贸然登机?反正我是不敢。但不少事故记录显示,某些飞行员就是没能尽到机体检查义务,最终引发了可怕的悲剧。


某公司虽然不是航空企业,犯错的代价也不是宝贵的性命,但事故仍然严重影响到企业的业务与信誉。如果情况再严重一些,这家公司可能将彻底不复存在。


总而言之,在“某公司”里,存在着三份变更清单:


1)预生产清单;2)生产中清单;3)生产后清单。

预生产变更清单:

  1. 在团队日历当中安排 push 至生产环境的时间。

  2. 对 PR 进行审查与批准。

  3. 相关团队测试并批准各项变更。

  4. 由指定的测试人员确保所有测试用例均正常通过并符合要求。

  5. 提交申请与测试或者生产环境无冲突。

  6. 在台式机及移动设备上运行冒烟 / 回归测试。

生产中变量清单:

  1. 发布流水线中无即时事故(build 失败)。

  2. 在此期间,不存在其他部署申请。

  3. 在 Slack 中通知部署已经开始。

  4. 按下“红色按钮”开始 push 至生产环境。

生产后变更清单:

  1. 检查部署脚本日志以了解部署是否成功。

  2. 在台式机及移动设备上运行冒烟 / 回归测试。

  3. 以一小时为周期,监控所有日志及统计图表。

  4. 通知变更相关团队。

  5. 如果没有问题,在 Slack 当中宣布部署成功。


很明显,其中不少步骤都有可能发生问题,而产生问题的原因就是执行人员看不到环境的整体情况。


下面,我们从三个角度提出问题:


  1. 为什么会出问题?

  2. 本应以怎样的方式加以预防?

  3. 某公司在事后做了什么?

事故分析

先来看看问题为什么会发生,又怎么会导致大量日志丢失。


  1. PR 当中包含对某行代码的微小变更,可能影响巨大,但相关描述非常模糊。

  2. 在同一 PR 当中,三分之一的程序流并未经过王二的实际测试,因为他觉得抽查当中没发现问题就够了。

  3. 代码审查员没有注意到这一微小的变更。

  4. 王二并没有在测试中检查这些即将受到毁灭性影响的日志(注意:公司当中根本没有质量保证人员这一职务)。

  5. 身兼测试人员与代码审查员两职于一身的王二没有注意到代码未发送记录请求的问题(注意:因为没有质量保证人员,所以代码审查员必然同时兼任测试人员)。

  6. 在 push 至生产环境后的监控环节当中,由于图表中的变化与其他长期记录相比非常微小,所以日志记录丢失问题没能被及时发现。

  7. 不存在对日志及图表的每日监控机制,因此没人第一时间注意到这个问题。

  8. 下一条部署至生产环境的 PR 同样没有正确遵循检查流程,且 / 或测试人员与第 6 条一样未能发现图表中的微小变化。

本应以怎样的方式加以预防

本应执行周期为七天的日志检查

开发人员往往只会检查发布过程中 1 到 4 小时周期内的日志。这就意味着,如果 4 小时前生产系统曾经发生某些异常,那么测试人员将无法发现。理论上来说,这样的问题忽略循环可能永远存在。


事实上,王二在后来对七天内日志记录进行检查时,发现了多项错误。但到目前为止,某公司还没有任何人——从管理层到开发人员——认为有必要把监控周期设定为七天。时间本身也并不是问题,开发人员可以快速切换日志显示区间来查看过去 1 小时、1 天或者 7 天当中的记录内容。

每日监控

目前公司内缺少适当的每日监控机制。监控只在清单列出的变更周期内进行,此外不再单独投入时间。一种解决办法,就是在每天工作结束时强制要求检查日志内容。


我在拉脱维亚的 Evolution Gaming 公司工作时,团队采取的是职务轮换机制,大家轮流负责检查 Sentry 错误日志、审查待处理的 PR、向团队通报审查结果以及进行日常维护等等。在整个冲刺周期(2 周)当中,大家一直身兼常规职务与每日轮换职务两种角色。为了确保所有要求都能得到严格遵循,我们还在流程中添加了一种游戏化机制,即每一次 PR 审查都对应一定的分数奖励。


虽然大家都承认审查工作的意义,但在实际执行中,大多数人其实并不情愿把时间“浪费”在这件事上。因此,激励制度是种提升审查参与度与积极性的好办法。


某公司也可以在监控方面采用相同的方法。毕竟对大多数企业来说,用稍稍放慢一点速度的代价换取更高的发布质量无疑是划算的,而且从长远来看对每个人都有利。

双批准或者多批准模式

在我待过的团队中,但凡代码审查效果出色的,都至少要对每条 PR 进行双重批准。事实证明,这种多轮把关的方法相当可靠,因此我后来自己单飞后,也继续在个人外包合同中继续沿用这一模式。


单批准模式的主要问题在于……举个例子,大家见过只有一名飞行员的航班吗?万一其中一人忘记开启控制面板上的某个开关,至少还有另一位及时提醒提醒。

提高测试质量

无论是单元测试还是集成测试,我们都该将其视为保证生产安全的一道有力屏障。


很明显,某公司内的集成测试并没有覆盖到代码中的重要变更部分。事实上,这家公司压根就没把集成测试纳入王二团队的测试范畴,甚至多次打回了要求进行集成测试的申请。这并不是因为集成测试在技术上有多困难,只是因为上下级沟通不畅、缺乏主动性以及无知。


从主观上讲,大多数开发人员不愿进行测试的头号原因,是“我为什么要在代码已经能够正常运行的情况下,因为「不必要的麻烦事」而拖慢部署进度?”


而第二号原因,就是截止日期被压得太紧。


说起单元测试,很多朋友都觉得这就是走个过场,毕竟我们很难量化单元测试到底阻断了多少错误。


这里要强调一下,单元测试确实可以防止开发期间出现的大量错误。我们的项目需要在 push 至生产环境之前就进行过测试,这样即使 1 项测试失败,合并尝试都将中止。这就给了我们解决问题并再次 push 的时间窗口。


更重要的是,我们可以在测试运行期间严密观察。我发现很多开发人员没有养成在后台运行测试的好习惯,而由此带来的恶果,就是在问题出现后大家需要耗费大量时间回溯一切变更。


当然,即使是在观察当中,出现的大量问题也有可能让我们迷失在修改的漩涡当中。这个问题可以通过科学的重构方法进行预防。Martin Fowlers 在书中建议以积极的心态进行重构,例如在发生测试失败时,请还原最后一项变更并确保不影响测试环境。他提出的方法可以概括为“一次只改一行”。当然,我们也可以根据实际情况灵活调整,比如“一次只改两行”之类。


接下来是 TDD。有研究表明,TDD 能够帮助我们将项目中的 bug 减少 40% 到 90%。但这种从长远来看收益丰厚的方法,却往往遭到开发人员的激烈反对。不过如果各位不打算破产或者失业,还是请把 TDD 严格贯彻到位。较高的测试标准,也将为您带来更强的比较竞争优势。

实施集成测试

当然,单元测试可能很难覆盖到某些代码流,甚至相关测试更像是集成 / 单元测试的结合体。这确实是种比较棘手的情况,这里我推荐大家了解 Sandy Metz 给出的建议:



如果能在开发过程中节约成本,不妨打破规则。——Rails Conf 2013 大会,Sandy Metz


我可能会考虑在单元测试中采用集成测试方法来覆盖这次引发问题的代码行,从而尽量缩小范围。对问题进行充分记录,并在测试完成后尽快清除集成测试部分。


当然,我并不是集成测试方面的专家,但在这种情况下,集成测试确实能够防止数据日志丢失。

极限掌控力

我想聊的最后一点,来自 Jocko Willinks 的《极限掌控力》一书。我坚信,变更清单检查不足的责任,有相当一部分要由团队主管(包括技术主管或者项目经理)以及开发人员本身来承担。


开发人员与质量保证人员之所以没有严格遵循检查流程,是因为他们并不清楚这项工作的重要意义,以及一旦出现偏差有可能带来怎样的严重后果。当然,这也可能是因为主管人员不太了解流程中的某些组成部分。在这种情况下,开发人员与质量保证员必须抱有“一路上报,直到解决问题”的坚定态度。

某公司在事后做了什么

在这条 PR 被 push 至生产环境的七天之后,某公司决定开发用于比较服务器与客户端日志内容的系统。这套系统能够在服务器与客户端日志间存在差异时及时发出通报。


王二团队开始引入每周日志监控流程,但是主管仍然没有亲自跟进这项工作。


幸运的是,公司管理层已经开始进行对话,探讨如何解决未来可能出现的类似问题。


在业务流程改善方面,存在着大量可供企业选择的具体方案,而这些方案能够有效预防代码引发的内部或者外部事故。但遗憾的是,我们人类天然具有一种懒性或者说消极性,那就是只会在遭遇灾难之后才真正意识到预防准备的重要意义。

原文链接

We Crashed and Lost All Essential Data Logs. Where Did We Go Wrong?


2019-11-28 10:115743
用户头像
小智 让所有人认同的文字称不上表达

发布了 408 篇内容, 共 403.2 次阅读, 收获喜欢 1986 次。

关注

评论

发布
暂无评论
发现更多内容

2025 用户力荐的国内 RPA 工具,哪款才是你的最佳之选?

Techinsight

RPA RPA评测 RPAxAI RPA Agent

观测云产品更新 | 场景、日志、可用性监测等优化

观测云

产品迭代

爱橙科技基于 MaxCompute 智能物化视图最佳实践

阿里云大数据AI技术

大数据 阿里云 SaaS MaxCompute 物化视图

SonarQube Server 2025 Release 2 发布 - 代码质量、安全与静态分析工具

sysin

SonarQube

项目过程中会出现哪些问题?

秃头小帅oi

Hologres诊断与优化快速入门

阿里云大数据AI技术

数据库 sql 大数据 阿里云 hologres

HarmonyOS NEXT 中级开发环境搭建与实用工具类 AI 问答 APP 开发

yimapingchuan

HarmonyOS NEXT

实用干货!快速掌握 RPA 的实战学习方法

Techinsight

RPA RPA评测 RPAxAI RPA Agent

豫中南数字产融平台上线87日交易额破亿,重塑产业新生态

科技热闻

怎么在线快速制作PPT?5个PPT生成工具盘点!

职场工具箱

职场 PPT 办公软件 AIGC AI生成PPT

Web3项目的安全性

北京木奇移动技术有限公司

区块链技术 软件外包公司 web3开发

必看!SpringAI轻松构建MCP Client-Server架构

王磊

AI低代码MES:制造业从“制造”到“智造”

万界星空科技

AI 低代码开发 低代码平台 mes 低代码云MES

5000万考生救星!百度网盘和文库首发一站式视频AI笔记

极客天地

养老机构平台运营与开发:数字化时代的智慧养老解决方案

网站,小程序,APP开发定制

AI应用如何从 Chat 进化为 Agent?开源项目源码深度揭秘|得物技术

得物技术

agent 大模型应用

深度剖析 StarRocks 读取 ORC 加密文件背后的技术

vivo互联网技术

数据库 大数据 加解密 StarRocks orc

软件架构,关于问题起源和应对

伤感汤姆布利柏

火山引擎智能数据洞察 ChatBI 适配 DeepSeek-R1 及 DeepSeek-V3

火山引擎开发者社区

测试框架设计的艺术

FunTester

币安再度封禁违规做市商,Crypto 行业还有多少「蛀虫」

TechubNews

比特币

DeepSeek 3FS 架构分析和思考(下篇)

火山引擎开发者社区

软件产品开发中常见的10个问题及处理方法

伤感汤姆布利柏

国产服务器操作系统CTyunOS,技能值拉满!

天翼云开发者社区

云计算 服务器操作系统

解锁RPA数据采集隐藏技能,这些优势你get了吗?

Techinsight

RPA RPA评测 RPAxAI RPA Agent

Web3项目的开发框架及特点

北京木奇移动技术有限公司

区块链开发 软件外包公司 web3开发

智能制造:自动化焊装线的数字化设计

积木链小链

数字化 制造业 智能制造

DeepSeek Smallpond 在火山引擎 AI 数据湖的探索实践

火山引擎开发者社区

Web3项目开发流程

北京木奇移动技术有限公司

软件外包公司 web3开发 区块链开发公司

数字先锋 | 打造专属AI大脑,天翼云助力重庆理工大学开启智慧校园新篇!

天翼云开发者社区

人工智能 智慧校园

Web3项目的上线流程

北京木奇移动技术有限公司

区块链开发 软件外包公司 web3开发

事故复盘:我们是怎么弄丢1400万条日志记录的_软件工程_Rolands_InfoQ精选文章