利用 Production Tests 提升系统质量和睡眠质量:一份实用指南
Production tests: a guidebook for better systems and more sleep
作者:Martin,分类:General
你的客户期望你的网站在任何时候都能正常运行。这意味着你不仅要追求网站本身的近乎完美的正常运行时间,还要保证客户可能使用的所有功能的可用性。
现代软件工程采用质量控制措施,如自动化测试套件和可观测性工具(tracing、metrics 和 logs)来确保可用性。在这个领域中,经常被忽视的是 production tests(也称为 synthetics),它可以让你立即收到生产环境中故障的通知。
设置 Production tests 非常简单——通常在一个 sprint 内就能完成——并且可以提供很高的投资回报。在这篇文章中,我将介绍如何最好地设置 Production tests,以及它们如何帮助提高可靠性、部署和可观测性。
虽然我一直很喜欢 Production tests,但我真正在 Atlassian 对它们有了真正的了解,在那里它们被广泛使用,被称为“pollinators”,我亲眼目睹了它们如何提供问题的早期预警,从而可以在问题演变成事件之前修复。
什么是 Production tests?
Production test 是任何在生产环境中运行的自动化测试。测试会按预定的时间表频繁运行,以便 on-call 工程师能够快速响应。通常,它们每分钟运行一次。测试可能会使用 headless browser 来模拟用户操作,或者它可能直接使用 API 来模拟浏览器代码或后端服务的操作。
Production test 应该在合理的时间内运行完毕。我建议 30 秒或更短,这样你就可以轻松地每分钟运行一次测试。耗时超过 30 秒的测试对于 Production test 来说可能太复杂了。测试如何处理故障取决于你的团队。它可以与你的 on-call paging 系统集成,发送 Slack 通知,或者只是将错误记录到你的日志系统中。
Production tests 如何提供帮助?
Production tests 通过立即警告回归,帮助你的生产环境更加可靠。这意味着你可以在客户发现问题之前修复它们。
此外,Production test 可以在部署之前用作 canary,因此可以充当集成测试。该测试可以检测到由与其他服务不匹配引起的回归,例如 API 形状或错误处理问题。你也可以在部署到开发和 staging 环境时运行测试,以便在开发过程中收到问题警告。
通过拥有 Production tests,你还可以更轻松地调试生产问题。如果你正在调查问题,了解哪些 Production tests 正在工作以及哪些正在失败,可以让你深入了解问题可能是什么。如果你依赖其他团队的服务,并且他们也有 Production tests,你可以查看他们的测试来帮助诊断。
拥有 Production tests 将减少人为修复事件的恢复时间,因为工程师可以更快地了解问题,并掌握更多信息来解决问题。
Production tests 的重要设计考虑因素
为了使 Production tests 具有价值,它们需要经过深思熟虑。如果测试一直失败,它可能会被忽略和静音。即使测试可靠,也可能导致其他问题,例如资源使用影响下游系统。你甚至可能需要更改你的系统以使其更具可测试性。以下是一些在设置 Production tests 时要考虑的技巧:
保持你的 Production tests 简单
你的 Production tests 应该比你的自动化测试套件覆盖更少的范围。你希望测试足够可靠,以免因虚假警报而浪费你的时间,这会导致沮丧、浪费时间和可能禁用警报。Production test 的目标是成为金丝雀,表明某些事情已经严重出错。它可以让你抢先修复它,希望在客户受到影响之前。
为了说明所需的简单性,以下是一些我认为是 Production test 良好候选者的示例:
- 登录,并确认你在主页上,显示用户的姓名。
- 加载你的应用程序的主要编辑器并键入 Hello。确认 Hello 在那里。重新加载浏览器并确认 Hello 仍然在那里。
- 调用 4 个 API endpoint 对你的 microservice 进行 CRUD 操作,可能在 API 中使用一些假数据。
- Ping /health 并检查 250 毫秒内的 200 响应代码。
相比之下,这些更复杂且有问题的 Production tests:
- 运行一个 25 步的测试,检查编辑器的所有主要功能,断言元素是正确的大小并且位于正确的位置。
- 测试如果你快速连续地调用 API,它们将以相同的顺序添加到数据库中。
- 检查信用卡页面是否可以根据卡号区分 Visa 和 Mastercard。
- Ping /health 并检查 1.5 毫秒内的 200 响应代码。
第一个示例很好,因为它们快速、可靠且简单。它们不是太具体于功能的,因此不太可能因功能更改而中断。
另一方面,不好的例子存在问题:
由于浏览器自动化怪癖和功能更改,25 步测试很可能会不稳定。你将花费大量时间调查测试失败,并得出结论“这只是一个一次性事件”或“哦!那是因为我们移动了一个按钮”。
由于网络状况改变了接收请求的顺序,快速连续的 API 调用有时会失败。在 Production test 中没有必要做一些复杂的事情——你的目标是知道某些东西是否严重损坏,而不是检测微妙的计时问题。
信用卡测试在不不稳定的方面可能还可以,但有点太具体了。你几乎可以通过在部署之前运行的测试来完全消除信用卡 UI 行为中的错误风险,所以请这样做。
期望 快速 响应的健康检查测试可能会经常失败,从而导致没有有意义的响应的警报。有更好的方法来监视生产中的延迟,我将在以后的文章中介绍。
但是……尝试获得一些体面的覆盖率
你的目标不是接近 100% 的代码覆盖率,事实上代码覆盖率在这里并不重要。也就是说,Production tests 应该不仅仅覆盖“加载主页”。这是一种艺术,但这里的指导思想是“如果存在严重问题,我的 Production tests 有多大可能检测到它”。你正在平衡“我多久会收到中断的虚假报告”。
你可能还需要考虑你正在测试的事物的价值。这是一个由 1% 的用户使用的小功能,还是新客户注册的页面?对于严重依赖客户自助服务来试用其软件的成长型公司来说,后者尤其重要。
你不必从一开始就完全正确。你可以在下周添加更多测试。此外,你还可以编辑现有测试,甚至删除它们。一开始倾向于太少的覆盖率,并考虑稍后添加更多。这样,你的团队将习惯于拥有、调整和响应 Production tests,而不会出现警报声!
作为一个粗略的指南,我会说首先测试 3-5 个简单的事情,目标是最终朝着合理的覆盖率发展。什么是合理的?在尝试事情并与你的团队讨论结果后,你会发现的。这里没有正确的答案。
Production tests 不是健康检查,但可能与它们重叠
健康检查通常是对服务器是否正在运行的简单检查。例如,如果使用 Node.js 和 Koa 或 Express,你可以添加一个健康路由,该路由仅在任何调用时返回成功响应。
此检查的目的是评估基本服务器健康状况。它允许负载均衡器知道将流量发送到哪些节点,并允许部署管道知道部署何时完成(或失败)。
我们期望这些健康检查在生产中失败,可能不会影响客户。例如,如果一台机器脱机,负载均衡器将检测到这一点并停止向该节点发送流量。但是,如果这对消费服务或客户没有不利影响,那么就没有 紧急 问题。系统已自我修复。
建议不要在节点上调用此健康检查作为 Production test,因为它会导致虚假警报。即使没有,健康检查也不是用户体验的好指标。
术语“健康检查”有时也用于指不仅仅检查服务器是否启动的检查。例如,他们可能会检查存储系统、缓存、队列等依赖项。调用此类健康检查的 Production test 可以在问题变得被客户注意到之前发出早期警告。
请注意你的 Production tests 如何影响可观测性
每分钟运行一次测试,或每天运行 1440 次,会在 logs、metrics 和 traces 中显示很多。这通常是一件好事,因为流量非常低的区域或服务现在比没有此类测试时更“可观察”。
缺点是它可能会通过在这些区域中保持资源运行来增加成本。另一个缺点是作为虚假流量,有时需要虚假数据(例如虚假用户 ID)会给日志增加噪音,你有时需要过滤掉这些日志。
虚假数据注意事项
考虑一个单体应用程序——一个服务网站及其所有功能的单个服务器。你需要编写一个测试,该测试登录,在字段中输入一些数据,保存它并检查它是否已保存。这样的测试有一些挑战。
首先,你需要决定如何登录。它是否有真实帐户?如果是——是什么阻止该帐户过期(例如,来自免费试用)。你可能需要一个折扣代码或特殊的“假信用卡”,系统知道这是用于测试的。如果它是“假”帐户,那么它是如何工作的?它是否硬编码在某处。
该测试现在每次运行都会生成数据。先前运行的成功或失败是否会影响测试的当前运行。每周运行数千次测试会占用存储空间吗?
在计划测试时请考虑这些问题。
最诱人的是做最容易完成的事情。例如,使用你的员工电子邮件创建一个帐户,稍后担心存储,只需让它工作即可。如果测试稍后中断,并且你需要处理升级帐户,或者可能使用其电子邮件的员工正在休假,这可能会困扰你。
使生产系统可测试可能需要一些工作并具有特殊的开关,例如用户字段或功能标志,以便可以稍微更改行为以方便测试。
如果你使用 microservices 或具有单独的身份验证服务的 monolith,则可以通过多种方法避免需要测试用户帐户。例如,如果你的服务使用 JSON Web Token (JWT) 进行身份验证,则身份验证服务器可以支持测试系统的登录,并且你的服务可以声明它授权哪些测试来调用它。
三次失败才发出警报
如果你有足够的 Production tests,并且在足够的系统上运行足够长的时间,你将收到虚假警报。这些可能是由各种原因引起的,仅影响测试端的网络问题,浏览器自动化中的怪癖,或在两秒钟后自行修复的真正问题。
避免获得这些类型的虚假警报的简单方法是在发出任何警报之前等待连续三次失败。
你现在可能正在侧眼看我,因为我们应该忽略这些虚假警报吗?可能不是。如果你有一个查看操作数据的团队仪式,你可以将非警报 Production test 失败纳入该仪式中。这个想法是你像任何常规工作一样对其进行优先级排序,而不是将其变成需要人们在下班后工作或停止其常规工作的紧急事情。
Production tests 的优缺点
在生产中进行测试有什么好处?我已经暗示了其中的一些,但是让我们深入了解细节:
- 真实世界测试: 绝对需要测试套件——包括单元测试和本地运行的集成测试——每次构建时都会运行。但是,即使有了所有这些,也没有什么比试驾完成的汽车更好的了,而这正是 Production tests 的用途。事实胜于雄辩。
- 质量控制: 运行测试的主要原因是知道某些东西已损坏。尽管你在你的机器和 staging 环境中进行了所有自动化和手动测试,但生产始终是独一无二的。有些事情只发生在他们 prod 中的方式。即使你的 staging 环境完全相同,一般来说生产的流量会更大。在生产中运行测试可让你知道某些事情是否在生产中运行。
- 故障排除: 如果发生事件,客户受到错误或中断的影响,则测试非常有用。它们可能会失败或通过,但无论哪种方式,它们的当前状态都会告诉你有关系统的信息,并且可以帮助缩小问题范围。
- 低流量区域的可观测性: 如果你将你的服务部署到多个区域,并且其中一些区域没有获得太多流量,则 Production tests 将创建合成流量。即使每天只有 1000 个调用,你的可观测性指标(如延迟和可靠性百分位数)也将比流量接近零时更有意义。
- 更安全的部署: 你用于监控生产的相同测试可以兼作你运行以接受蓝/绿部署的测试。然后,这些测试充当最后的持续集成测试,从而增加了你的部署不会引起大问题的保证。
- 在其他环境中重用: 正如你可以使用这些测试进行更安全的部署一样,你也可以在 dev 和 staging 环境中使用它们,以尽早检测到你的构建管道无法检测到的问题,例如与其他服务的集成问题。
当然,使用 Production tests 也有一些缺点:
- 设置和拆卸挑战: 测试在真实系统上运行,因此你不能在每次运行前擦除数据库。你需要弄清楚如何最好地设置你要测试的特定场景,以及如何在测试后进行清理。
- 它们有时需要设置场景: 例如,你有一个你可以升级你的帐户的测试,但是你需要一个需要升级的帐户,以及一个将被接受的假付款方式。这些场景可能意味着更改生产代码以支持它们。
- 它们可能会不稳定: 在真实系统上运行的任何测试有时都会因各种原因而失败。例如,测试和服务之间的网络问题,或者测试使用的浏览器中的偶尔计时问题。如果你打算在测试失败时唤醒某人,则需要考虑测试的不稳定性。
- 它们会导致资源使用和成本: 运行测试确实会产生费用。通常,测试会在不同的地理区域运行,以确保它们得到很好的测试,并且每天会运行数百次。该计算成本加起来。
- 维护测试的人力成本: 并非每个测试失败都是问题,但确实需要进行调查。太多的测试可能会让你全职监控并使这些测试更加健壮。
Production tests vs. 可观测性
你还可以通过监视真实流量并在那里寻找问题来“测试生产”。这值得单独发表一篇文章或一系列文章,但简而言之,你可以检查以下内容:
- 延迟,例如,当特定 endpoint 的前 99 个百分点的延迟 > 200 毫秒,且连续出现 3 个周期时,发出警报。
- 可靠性,例如,当超过 0.1% 的请求因 5xx 代码而失败时,发出警报。
- 断言,例如,当触发被认为意外或不可能的代码路径时,发出警报。
- 失败,例如,当客户由于收到错误而无法执行任务时,发出警报。
基于可观测性的警报的好处是它们非常易于设置。它可能需要一些小的代码更改,然后在可观测性工具中设置检测器,这些检测器会查找并在满足条件时采取行动。
这些测试与 Production tests 相得益彰。但是,它们有不同的目的,因为它们在问题发生后检测到问题,并且它们依赖于现有的系统使用。可以通过 Production tests 创建额外的合成流量来帮助他们,然后他们可以监视这些流量,这使你可以在自然流量水平下降时继续检查事物。
但是没有“与”!你最好两者都有。对于特定需求,最好使用 Production test 或更好的是使用可观测性。一个经验法则是,如果可观测性可以满足向你发出问题警报的要求,那么它将比 Production test 更容易设置和调整以满足你的需求。
总结
唷!我们涵盖了很多内容。简而言之,向你的系统添加精心设计的 Production tests 将在许多方面有所帮助。你将获得问题的早期警告,你将能够更快地修复它们,你将获得可观测性优势,并且你还可以将 Production tests 用作部署推出测试。
如果你还没有这样做,那么值得添加 Production tests——这是一个相对较小的任务,可以纳入你的计划中,你将获得回报。如果你已经在使用它们,请继续查看它们,并查看你需要添加、删除和调整哪些内容,以便在你系统发展时从中获得最大价值。
祝测试愉快!
最终说明:
希望这对你有所帮助并且有趣。如果你在下面留下你的姓名/电子邮件,我将不胜感激,我可以让你及时了解新的帖子。我大约每两周发布 1-2 篇,但这并不是承诺!类似于订阅 Substack 的想法。
名 邮箱
文章导航
Previous: LanguageTool — Check your writing the open-source way
发表评论 取消回复
电子邮件地址将不会被公开。 必填项已用 * 标注 评论 * 姓名 * 邮箱 * 站点 在此浏览器中保存我的姓名、电邮和网站。 Alternative: WPA