@GergelyOrosz: 2024年曾对Antithesis进行深入探讨,其多重宇宙调试器耗时多年开发。现已成为免费文章…

X AI KOLs Following 工具

摘要

对Antithesis的深入探讨,这是一款针对大型分布式系统的多重宇宙调试器,提供确定性重放和故障注入功能,现已作为免费文章发布。

2024年曾对Antithesis及其耗时多年开发的多重宇宙调试器进行深入探讨。现已成为免费文章(原为付费):https://t.co/CcqLf9SWLN
查看原文
查看缓存全文

缓存时间: 2026/06/13 01:06

2024年我深入研究了Antithesis,以及他们耗时多年打造的多元宇宙调试器。这篇文章现在免费开放(原为付费文章):https://t.co/CcqLf9SWLN


如何调试大型分布式系统:Antithesis

来源:https://newsletter.pragmaticengineer.com/p/antithesis 以下是对Antithesis的深度解读,写于2024年11月。本文原为付费订阅专享,于2026年5月免费开放。

快进到2026年,Antithesis发生了巨大变化:你现在可以将想要测试的服务或软件(即“被测系统”,简称SUT)部署到一个充满敌意的环境中,这个环境的唯一目的就是帮你找出其中的故障。这一切都是确定性的且可完全重放,因此你可以轻松复现任何发现的Bug。

这个环境实现了一些非常酷的功能。例如,它可以将24小时的测试运行压缩到30分钟内:

[图片链接] Antithesis 用户界面

这个环境有点像混沌工程的极限版本。它既有向系统投入的随机输入(类似于模糊测试),也包含蓄意的故障注入。

Antithesis 是《务实工程师播客》2026年夏季的首席赞助商。了解更多关于 Antithesis 的工作原理:我非常欣赏他们团队的雄心壮志。

调试是所有工程师都会做的事情,但几十年来,我们的调试方式几乎没有什么变化。例如,即使有可以在IDE中使用的相当不错的调试器,通过打印到控制台输出来进行调试仍然是相当普遍的做法。

信不信由你,如今的一些调试工具实际上比过去还要落后。Sourcegraph 工程主管 Steve Yegge 去年曾表示:

“我在1990年GeoWorks公司见过我用过的最好的调试器。直到今天,我还没见过哪个调试器能做到他们当时能做到的事情:动态路径选择、即时撤销、或者反向单步执行指令。”

这种停滞不前的进展使得一个专注于构建更好调试工具的小型工程团队的出现显得格外引人注目,该工具专门用于调试大型分布式系统。它就是 Antithesis,也是本文的重点。

今天,我们将涵盖:

  1. 调试简史
  2. Antithesis 的“多元宇宙调试器”
  3. Antithesis 联合创始人 Will Wilson 问答
  4. 技术栈
  5. 工程团队与文化
  6. 更好的Bug管理高级测试工具
  7. 利用高级测试工具进行更好的Bug管理
  8. 复杂性的取舍

调试和软件开发自计算机早期以来就紧密相连。但我们为什么称之为“调试”?其词源有点模糊,但可能真的和一只现实中的昆虫有关。

1947年,包括计算机科学先驱 Grace Hopper 在内的哈佛大学科学家团队发现一只飞蛾被困在马克II大型主机的继电器中,导致了机器故障。这个故障被记录下来,这只飞蛾本身也被贴入手写记录中,上面写着:“……发现并捕获的第一个真正的Bug实例。”

在此之前,故障就已经被称为“Bug”,但这个偶然事件可能有助于巩固“调试”一词在行业词汇中的地位。20世纪50年代的几篇计算机科学论文都顺带提到了“调试”,这表明这个词当时已被使用,其含义在专业人士中已是常识。它甚至还出现在1963年首个分时操作系统——兼容分时系统的手册中。

程序员们一直在构建工具以简化工作,调试器就是一个很好的例子。以下是自20世纪60年代以来工具集的演变过程。

20世纪60年代:穿孔卡片时代。 最早的调试工具:

  • 打字机调试: DEC调试磁带:一个在打字机上运行的调试程序!它允许在大型机运行时修改程序或其数据。(DEC代表“数字设备公司”,当时一家主要的计算硬件公司)。查看命令的完整手册。
  • 在线调试工具:一系列调试程序,允许在软件运行时使用八进制地址访问内存。同样由数字设备公司开发。

20世纪70年代:(符号)调试器。 像C语言、FORTRAN和COBOL这类新的、强大的编程语言在70年代被开发出来,它们允许获取显示变量内存地址的符号映射。符号映射用于更高效的调试,因为它们无需手动跟踪内存地址。今天使用的工具就是符号调试器。

20世纪70年代末:断点。 在能够检查运行中程序的内存并获取内存转储后,下一个调试任务就是在给定条件下暂停程序执行,例如变量达到某个特定值。断点正是为此而生。

暂停程序执行的核心功能出现在20世纪40年代,涉及多种方法,如拔线缆、故意导致程序崩溃,以及通过硬件开关。随着时间的推移,断点的实用性和易用性不断进化,到70年代末,它们以今天可识别的方式出现在符号调试器中。更高级的工具增加了允许程序前进一步的功能和更复杂的后退功能。

20世纪80年代中期:“现代调试”。 从20世纪80年代开始,软件开发体验随着更好的终端、更强的交互性和更紧密的反馈循环而持续发展。调试的改进也遵循了类似的模式。例如,1983年Turbo Pascal在其IDE中引入了内置调试功能——这可能是第一个具备调试功能并进入“主流”的IDE。

具有可视化断点和输出的图形调试工具是这一时期的创新。随着互联网的普及,远程调试(调试在网络上运行的程序)也成为可能。

今天的现代调试工具拥有现代特性, 例如:

  • 时间旅行调试。 也称为“反向调试”,在函数式编程和确定性环境中最为常见。它允许重现问题,并“向后回溯”以找出根本原因。今天的深度解读就聚焦于这样一个工具:Antithesis。
  • 记录与重放调试。 在进程的每一步都记录应用程序状态,并且可以重放。记录通常包括内存状态、内存交互、输入和系统资源状态标记等。ReDevBug 就是做这个的。
  • 自动调试。 能够自动定位,有时还能修复代码中Bug的工具。这些调试器通常由机器学习或人工智能驱动。
  • AI辅助调试。 最新一波调试使用生成式人工智能以更高效的方式预测和定位Bug。目前仍处于早期阶段,但我们可以期待更多此类解决方案。

Antithesis 成立于2018年,愿景是寻找更好的系统测试方法,并筹集了惊人的4700万美元种子资金。其商业模式是基于使用量的定价,根据用于测试活动的CPU数量计费;一个很好的类比是亚马逊租赁其EC2服务器。据我所知,目前Antithesis以年度预留的方式销售核心计算资源,有最低入门要求,并希望在未来提供更大的灵活性。

时间旅行调试工具通常局限于状态管理简单的函数式语言,或确定性环境,例如定义良好的沙箱。对于大多数现实世界的程序,调试时没有时间旅行选项可用。因此,当后端服务非确定性地崩溃时,没有好方法能扭转时间去调查它;通常最好的选择是增加更多日志记录以帮助解释未来的崩溃。

Antithesis团队花了数年时间构建一个像时间机器一样的系统。它包裹着你当前的系统,让你可以回退步骤。在这个“包裹”内,要将系统状态回退到5秒前,你只需输入:

branch = branch.end.rewind(5).branch

在过去五秒内删除的文件会恢复,包括那些被永久删除而未放入回收站的文件。自那以后对文件所做的任何更改也将被撤销。

创建时间机器意味着创建一个确定性模拟, 它可以从其起点任意地前进到未来。它也可以回到过去,这带来了有趣的可能性。例如,如果你的服务器崩溃了:能“回退”时间并附加一个调试器是不是很棒?在模拟系统中,你可以做到这一点:将系统模拟到进程将要崩溃的点,然后添加调试器或导出内存转储。类似地,如果用户报告他们的会话缓慢:现在可以通过重新创建他们的会话并附加调试器来“回到过去”。

拥有一个确定性模拟器可以创造以前难以实现的场景, 例如:

  • 跳转到未来; 例如,将系统快进10小时,以检查届时内存使用和CPU使用的趋势。这不是预测,而是允许实际检查系统的未来状态!
  • 生成更多可用的日志。 当在当前时间识别出可疑事件时,你可以回到过去,并在该事件可能起源的地方添加更多日志记录。你也可以在事件发生前的几分钟或几秒内启用整个系统的详细日志记录。
  • 改变过去。 回到崩溃发生之前,并修改正在执行的代码。

不过,Antithesis不仅仅是一个时间旅行调试器。一个很好的描述方式是,它是**“确定性模拟测试即服务”**。

确定性模拟测试是一种构建模拟的技术,软件可以在单个线程中运行,并且你可以控制所有变量(如时间、随机性等),以便在测试期间实现确定性。

[图片链接] 什么是DST?一份解释

DST是以下组合:

  • 模糊测试: 也称为“fuzz testing”,这是一种自动化测试,向程序输入无效、意外或随机的输入。
  • 断言: 做出总是应为真或假的逻辑陈述,并在断言失败时中断程序;例如,断言一个整数变量的值始终大于零,因此当此条件失败时程序中断。
  • 任意调试(Shotgun debugging): 对软件进行随机更改,看看是否能修复Bug。
  • 时间旅行调试: 能够在程序状态内“向前和向后回溯”。

对任何系统来说,进行确定性模拟测试都非常困难,因为你必须从头构建一切。没有现成的框架和库支持所有的时间旅行、调试、模糊测试等功能。DST最早的一次“正规”应用是在分布式数据库 FoundationDB 中,其创始人之一正是 Antithesis 的联合创始人 Will Wilson。

因为实现DST如此困难,Antithesis转而将计算机/虚拟机监控器变得确定性。这意味着,任何在此Antithesis计算机/监控器上运行的东西都可以用DST进行测试,无需自己动手做所有事情。

而且,通过运行一个完全确定性的环境,Antithesis可以有目的地将其操纵到奇怪的状态,这使得开发者可以检查奇怪的状态和Bug,以找出其原因。阅读更多关于Antithesis工作原理的信息。


该公司的CEO回答了我们的一些问题。在本节中,问题以斜体显示,Will的回复以普通文本显示。

Antithesis工具是为调试大型复杂系统而构建的,但这些系统与常见的单服务、单应用和单线程网站有何不同?

“有几件事使大型系统与众不同:

  • 怪异故障是必然的。 如果你的软件运行在一台计算机上,像内存中的位翻转或磁盘损坏这样的事情是极其罕见的。但如果你的软件运行在一个拥有数万台机器的集群上,你最好对此有所准备。
  • 期望通常更高。 如果你的软件运行在一台计算机上并且崩溃了,除了不丢失任何持久状态外,你的软件能做的改善情况的事情并不多。但如果你的软件运行在一个大型集群上,人们可能期望它在一两台机器宕机时仍能正常运行。
  • 并发性扮演更重要的角色。 单机上的多线程系统就可能让你陷入麻烦,但在多台机器以及它们之间不可靠/嘈杂的网络环境下,情况会糟糕得多。
  • 时间戳毫无意义。 除非你是谷歌,并且在数据中心里拥有原子钟,否则你必须假设不同机器上的时钟并非完美同步,这可能会让阅读日志变得非常混乱。你甚至可能无法确定一个事件是在系统A还是系统B上开始的!
  • 大型系统可能无法‘装进任何一个人的大脑’, 这使得用老式方法通过状态机推理变得更加困难。此外,构建这些系统所需的时间和人力都非常巨大,这意味着有更多机会丢失机构知识,或者记忆会模糊。”

“以上所有因素都使得大型系统的测试和调试更加困难,尤其是前三点。大规模系统的许多故障模式是‘外部的’或环境性的,与硬件故障、网络消息延迟或线程上的奇怪暂停有关。这些更难提前推理,而且测试和调试起来极其困难,因为它们可能依赖于几乎无法按需重现的高度特定条件或时间。

‘分布式系统的悖论在于,一个百万分之一概率的Bug可能是一个巨大的紧急问题, 因为你一直在处理数百万个请求,所以这个Bug会频繁出现。但它仍然是一个百万分之一概率的Bug,所以测试很可能无法复现它!’”

Antithesis在客户的软件交付和流程时间线中处于什么位置?

“我们看到客户以截然不同的方式使用Antithesis。有些团队几乎在每个PR上都运行简短的测试,或者……”

相似文章

@Apodex_AI: 深入阅读博客:https://apodex.com/blog/apodex-1.0 技术报告:http://apodex.com/pdf/20260608 GitHub:https://github.com…

X AI KOLs Following

ApodexAI 发布了 Apodex-1.0,这是一个深度研究模型,作为使用工具的 ReAct 代理运行。其重型模式 Apodex-1.0-H 采用异步代理团队,最多包含 150 个子代理,在深度研究基准测试(包括 BrowseComp、DeepSearchQA、HLE 和 FrontierScience)上取得了新的最先进结果,超越了 GPT-5.5-pro 和 Claude-Opus-4.8 等模型。