为调试而开发(2025)

Lobsters Hottest 新闻

摘要

Dave Pacheco 撰文介绍 Oxide 控制平面的 DNS 传播机制,以及如何围绕可调试性来设计系统,最终催生了 Omicron 调试器工具 omdb。

<p><a href="https://lobste.rs/s/a0og2j/developing_for_debugging_2025">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/10/17 08:50

# 为调试而开发 · Dave Pacheco's Blog 来源:https://www.davepacheco.net/blog/2025/developing-for-debugging-dns-propagation/ 作者 dap,发布于 2025 年 6 月 9 日 ## 为调试而开发 Oxide 控制平面运行着两种不同的 DNS 服务:对外 DNS 面向我们的客户,提供用于定位系统对外 API 和 Web 控制台的名称;内部 DNS 仅在系统内部网络中运行,为控制平面的各个组件提供服务发现。两者使用同一技术栈的独立部署。以下是基本要点: - DNS 数据的权威事实来源(即 DNS 服务器应返回的名称和记录)是控制平面数据库。这是一个强一致性的分布式数据库(CockroachDB)。 - 控制平面的核心是一个名为 Nexus 的组件。当发生应当触发 DNS 变更的事件时(例如,添加或移除了提供内部或外部服务的组件): - Nexus 首先更新数据库中的 DNS 配置。 - Nexus 中的一系列后台任务将更新后的配置传播到所有在运行的 DNS 服务器。这些任务在 DNS 相关事件发生时触发,也会周期性运行(以应对瞬时故障、遗漏的唤醒等情况)。 图示:DNS 传播 整个流程相对于触发变更的事件来说是异步的,但在正常运行的系统中通常几秒钟内就能完成。 但大家都知道,基础设施出问题时,永远是 DNS 的锅(https://www.cyberciti.biz/humour/a-haiku-about-dns/)。所以在开发这个系统时,我们花了一些时间思考:这个过程中哪些环节可能出错?当它坏了的时候,我们怎么知道原因? 具体来说:假设客户报告说他们期望存在的 DNS 名称缺失了。他们对外部 DNS 服务器进行查询时没有返回任何记录。可能是什么问题?可能是: - 数据库中的 DNS 数据有误。 - 传播过程出了问题: - 可能 Nexus 没有注意到 DNS 数据已更改。 - 可能 Nexus 持有的 DNS 服务器列表不正确。(例如,某个服务器被添加到了系统中,但没有加入传播列表) - 可能向 DNS 服务器传播 DNS 数据的过程出了问题。 - 可能传播过程卡住了。 - DNS 服务器可能根据其配置提供了错误的数据。 如果我们收到 DNS 行为异常的报告,很显然,我们希望有一个工具能够报告所有这些信息: - 数据库里有什么? - 哪些名称属于 DNS 配置的一部分? - 最后一次更新是什么时候?由哪个 Nexus 更新的?为什么更新? - 对于每个 Nexus 实例,最近一次传播尝试: - 什么时候开始的?还在运行吗? - 它正在尝试传播哪个版本的 DNS 配置? - 它发现应该向哪些 DNS 服务器传播?这是什么时候确定的? - 对每个服务器最近一次完成的 DNS 配置传播尝试的结果是什么? - 对于每个 DNS 服务器,它当前基于哪个版本的 DNS 数据运行? 这个例子是构建 `omdb`(https://github.com/oxidecomputer/omicron/tree/4f575a8a19a6d09e9d5ce8a5bd9a3e8ff867e97b/dev-tools/omdb)——即 Omicron 调试器——的契机。`Omicron` 是 Oxide 系统上控制平面的内部名称。之所以叫 Omicron 调试器而非 DNS 调试器,是因为我们意识到这不会是我们唯一需要运行时可观测性的子系统。[1 (https://www.davepacheco.net/blog/2025/developing-for-debugging-dns-propagation/#_footnotedef_1)] 我们构建 DNS 传播时基于一种名为**后台任务**(https://github.com/oxidecomputer/omicron/blob/4f575a8a19a6d09e9d5ce8a5bd9a3e8ff867e97b/nexus/src/app/background/mod.rs)的新抽象。后台任务内置了基本的可观测性。它们本质上就是带有一些特性的异步 Rust 函数:可以在特定事件发生时被调用(*激活*);也会周期性地激活;整个任务集合是静态定义的;可以返回任意状态载荷(目前是一个无 schema 的 JSON 对象)。有了这些组件,`omdb` 无需深入了解 DNS 传播的内部细节,就能生成一份有用的 DNS 传播摘要报告。首先,它能报告服务器提供的基本文档: ``` # omdb nexus background-tasks doc | grep -A1 "dns.*internal" note: Nexus URL not specified. Will pick one from DNS. note: using DNS server for subnet fd00:1122:3344::/48 note: (if this is not right, use --dns-server to specify an alternate DNS server) note: using Nexus URL http://[fd00:1122:3344:102::3]:12221 task: "dns_config_internal" watches internal DNS data stored in CockroachDB -- task: "dns_propagation_internal" propagates latest internal DNS configuration (from "dns_config_internal" background task) to the latest list of DNS servers (from "dns_servers_internal" background task) -- task: "dns_servers_internal" watches list of internal DNS servers stored in internal DNS ``` 然后是状态: ``` # omdb nexus background-tasks show dns_internal note: Nexus URL not specified. Will pick one from DNS. note: using DNS server for subnet fd00:1122:3344::/48 note: (if this is not right, use --dns-server to specify an alternate DNS server) note: using Nexus URL http://[fd00:1122:3344:104::3]:12221 task: "dns_config_internal" configured period: every 1m currently executing: no last completed activation: iter 4500, triggered by a periodic timer firing started at 2025-06-10T03:31:47.775Z (23s ago) and ran for 1303ms last generation found: 18 task: "dns_servers_internal" configured period: every 1m currently executing: no last completed activation: iter 4500, triggered by a periodic timer firing started at 2025-06-10T03:31:47.775Z (23s ago) and ran for 1ms servers found: 3 DNS_SERVER_ADDR [fd00:1122:3344:1::1]:5353 [fd00:1122:3344:2::1]:5353 [fd00:1122:3344:3::1]:5353 task: "dns_propagation_internal" configured period: every 1m currently executing: no last completed activation: iter 4502, triggered by a periodic timer firing started at 2025-06-10T03:31:47.775Z (23s ago) and ran for 876ms attempt to propagate generation: 18 DNS_SERVER_ADDR LAST_RESULT [fd00:1122:3344:1::1]:5353 success [fd00:1122:3344:2::1]:5353 success [fd00:1122:3344:3::1]:5353 success ``` 这就是我所说的**为调试而开发**的一个简洁范例:在构建系统时,我们假设系统的任何部分都可能在生产环境中意外出错。我们提前思考调试它时需要哪些信息,然后确保我们能从生产系统中收集到这些信息。 值得注意的是,一旦我们在后台任务等基本抽象上投入了精力,将 DNS 传播的各个部分拆分出来以获得这些状态报告,工作量非常小。但有了这些,只需几秒钟,我们就能准确判断传播管道在哪里断了。其结果是一个不仅能运行、而且可调试的系统。 ## 软件应该能为自己开脱 软件能告诉你它哪里出了问题,这很好。如果它能令人信服地告诉你它*正在正常工作*,那就更好了。 像这样的系统报告以下内容是一回事: 或者: > DNS 传播是最新的。 好吧。但这真的对吗?"0 个问题"意味着"这个程序知道的 0 个问题"。"是最新的"这个说法充其量是含糊的,而且在文字出现在你屏幕上的那一刻就可能已经过时了。 上面的系统在*正确*工作时会报告更有说服力的肯定证据:它会说"我已将 DNS 版本 18 传播到了这三个 DNS 服务器(我于 2025-06-10T03:31:47.775Z 发现的这些服务器),版本 18 是我在同一时间发现的,且三个服务器全部在 2025-06-10T03:31:48.651000Z 之前完成了传播。" 这提供了*多得多*的信息。很多时候,这可以告诉你 DNS *不是*问题所在。[2 (https://www.davepacheco.net/blog/2025/developing-for-debugging-dns-propagation/#_footnotedef_2)] 即使问题出在其他地方,这些信息也能帮助你构建事件时间线来弄清究竟发生了什么。也许用户在传播完成之前就查询了 DNS? ## 其他好处 以这种方式开发软件还有许多其他好处: - 你可以在构建系统时使用 `omdb` 来摆弄它、测试它,然后再编写自动化测试。我们在这里没有这样做,但你可以设想:先构建数据库部分,再构建其余的传播管道,然后用 `omdb` 观察 Nexus 何时注意到数据库的更新。调试器驱动开发是整期 Oxide and Friends (https://oxide-and-friends.transistor.fm/) 播客的主题。 - 你可以在改进现有系统时使用 `omdb` 来理解它的行为。在这个例子中,你可以设想观察某些 DNS 服务器离线时会发生什么。 - 你可以用 `omdb` 来教别人软件是如何工作的。DNS 子系统的入职文档(目前不存在,但应该有!)可以走查一个 DNS 变更及其后续传播的示例。导师可以向新成员展示它。一个这样详细程度的演示胜过一千张图。 - 你可以用 `omdb` 作为沟通软件变更的工具。与其向人们介绍新的 DNS 系统,你可以在 10 分钟内进行一次深入的 DNS 子系统演示,不仅展示 DNS 变更*已经*按预期传播了,还展示它是*如何*传播的,甚至展示出问题时会发生什么。 根据以往的经验,我可以这样说:当一个团队在整个系统中都做到了这一点时,调试信息的便利获取真的会改变处理支持电话时的情绪基调。很多人自然而然地把调试视为一种痛苦的干扰,是他们本想做的事情之外的事。当客户正在等待修复而你压力巨大时,情况就更加令人紧张。很多压力来自恐惧和不确定性。当你建好了这些工具,你就能更快(也更自信地)解决更多问题。知道客户在受苦当然还是不好受,但当你知道如何去排查问题时,就没那么可怕了。 我还有一种直觉:讽刺的是,以这种方式构建的软件反而*更不容易*出现运行时问题,因为这个过程常常促使你在开发阶段就去思考这些问题。我得承认,我没有数据来支持这一点。

相似文章

Virtual Oxide Labs:模拟一整套 Oxide 机架

Hacker News Top

Oxide Computer 介绍了 Voxel(Virtual OXidE Labs)——这是一套在单台机器上模拟完整 Oxide 机架的软件仿真栈,集成了 Propolis 虚拟化、FRR/BGP 网络、SoftNPU P4 交换机以及 SP/RoT 微控制器仿真,让产品保障团队无需使用特殊的测试版本,就能以真实的控制面软件进行高保真度的 CI 测试。

精准调试基准:你的模型在调试还是在重写?

Hugging Face Daily Papers

# 论文页面 - 精准调试基准:你的模型在调试还是在重写? 来源:[https://huggingface.co/papers/2604.17338](https://huggingface.co/papers/2604.17338) ## 摘要 前沿大模型在测试通过率上表现优异,但在调试任务中的精准度却很低,暴露出功能正确与精准定位缺陷之间的鸿沟。与代码补全不同,调试需定位错误并做针对性修改。我们观察到,前沿大模型在调试时往往重写出正确却过度修改的代码。

我的调试器有一半是 Nix 写的

Hacker News Top

作者介绍如何借助 Nix 的确定性 Rewind VM 构建调试器,利用 derivation 记录完整输入,实现可复现的竞态条件复现与精确定位,大幅降低了实现调试功能的难度。

Debug web apps with browser use in Codex

YouTube AI Channels

Codex 的 Browser Use 功能新增了 Chrome DevTools Protocol 支持,使开发者能够通过检查网络流量、性能分析和控制台日志等高级功能来深入调试 Web 应用。