依赖冷却期不公平;我们应该改用分阶段部署
摘要
本文指出依赖冷却期不公平地增加了较早时区开发者的负担,并提出基于项目标识符的确定性分阶段部署,以更公平地分配采用率。
<p><a href="https://lobste.rs/s/jyhbzg/dependency_cooldowns_are_unfair_we">评论</a></p>
查看缓存全文
缓存时间: 2026/05/21 20:18
# 依赖冷却期是不公平的;我们应该改用分阶段发布
来源:https://illegalcode.net/rfcs/phased_rollouts.html
## 键盘快捷键
按←或→键切换章节
按S或/键搜索本书
按?键显示此帮助
按Esc键隐藏此帮助
## Scott Takes
## 依赖冷却期是不公平的;我们应该改用分阶段发布 (https://illegalcode.net/rfcs/phased_rollouts.html#dependency-cooldowns-are-unfair-we-should-use-phased-rollouts-instead)
> 注:我不擅长写作,并且默认假设相关性发生在00:00 UTC。我对原稿做了小幅修改以强调这一点。
3月31日,墨尔本一个阳光明媚的早晨。开发者们啜着白咖啡,开始一天的工作,等待`npm install`完成。后面的故事你都知道了。Axios供应链被攻破发生在UTC时间00:21至03:15之间 (https://www.sans.org/blog/axios-npm-supply-chain-compromise-malicious-packages-remote-access-trojan),对东半球造成了不成比例的影响。事件之后,原本零星的关于依赖冷却期的呼声几乎一夜之间变成了行业最佳实践 (https://cooldowns.dev/)。
冷却期能有效应对快速发作的供应链攻击 (https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns)。但它有一个尴尬的特性:它隐式地依赖别人先安装。在常见的(恶意)实践中,这个“别人”指的是亚太地区:
- 00:00 UTC
- 08:00 中国
- 09:00 东京
- 11:00 悉尼
我提议,与其“所有人等待 N 天”,不如让包管理器基于稳定的输入(项目唯一标识符、包名、版本号、制品摘要)确定性地将项目映射到一个分阶段发布窗口。结果是形成全球分布式的采用曲线,而不是基于时区的金丝雀测试。
如果你更倾向于看代码而不是文字,这里有一段演示该想法的 gist (https://gist.github.com/quad/7bf90db449c87e42ec0f52d26ce8c19e)。
首先,让我们看看另外三个采用不同做法的社区:
## 杀毒软件 (https://illegalcode.net/rfcs/phased_rollouts.html#antivirus)
2010年4月,McAfee 5958 导致大量 Windows XP 系统变砖 (https://krebsonsecurity.com/2010/04/mcafee-false-detection-locks-up-windows-xp/)。他们的应对措施是分阶段发布 (https://www.mcafee.com/support/s/article/000002680),而不是“所有人等待24小时再更新病毒库”。他们面临的情况类似:供应商很聪明,但大多数客户不够专业。供应商投入于测试和监控。一旦出错,供应商通常是第一个发现问题的。
## 操作系统和固件 (https://illegalcode.net/rfcs/phased_rollouts.html#os-and-firmware)
CrowdStrike Falcon 一天之内瘫痪了 850 万台电脑 (https://en.wikipedia.org/wiki/2024_CrowdStrike-related_IT_outages)。这是历史上最大的宕机事件 (https://www.smh.com.au/business/companies/microsoft-outage-across-australia-brings-down-major-businesses-20240719-p5jv2w.html),登上了2024年7月20日《纽约时报》头版 (https://static01.nyt.com/images/2024/07/20/nytfrontpage/scan.pdf)。
那一次更新于 UTC 时间04:09推送,正值大洋洲和亚洲的工作日中午。最大的教训之一是“在逐渐增大的部署环中逐步发布” (https://homeland.house.gov/wp-content/uploads/2024/09/2024-09-24-HRG-CIP-Testimony-Meyers.pdf)。当然,我们很多人只是觉得大型企业遭遇大型企业问题是理所当然的。但想一想,2018年 Windows 1809 是第一个使用机器学习定向分阶段发布的更新 (https://blogs.windows.com/windowsexperience/2018/11/13/windows-10-quality-approach-for-a-complex-ecosystem/),此前曾出现广泛的数据丢失 (https://blogs.windows.com/windowsexperience/2018/10/09/updated-version-of-windows-10-october-2018-update-released-to-windows-insiders/#7RWi4RBxzIgULeMG.97)。
## 功能开关 (https://illegalcode.net/rfcs/phased_rollouts.html#feature-flags)
当我阅读所有关于冷却期的讨论时,最让我感到奇怪的一点是:我们对自己应用并不使用冷却期。我们先把部署发布到小规模群体,进行监控,然后逐步增加流量。持续交付社区将其概括为一个朗朗上口的短语:将部署与发布解耦 (https://www.thoughtworks.com/radar/techniques/decoupling-deployment-from-release)。
## 提案 (https://illegalcode.net/rfcs/phased_rollouts.html#the-proposal)
包注册中心与上述例子确实有根本区别:
- 操作系统更新之所以有效,是因为供应商控制着发布和分发
- 包注册中心是基于拉取的;它们不能直接决定谁获取哪个制品
- 因此:任何分阶段发布逻辑都必须存在于项目侧
这个机制很简单:每个项目独立地从稳定输入中推导出一个哈希值:
1. 唯一的`project_id`
2. 完全限定的包名`package`
3. 语义化版本号`version`
4. 制品摘要`digest`
然后将哈希值映射到一个分阶段发布窗口上;我的示例代码使用`(14天) * sqrt(h)`,这样发布曲线偏向早期采用,同时仍然为检测留出一个长尾:
(14天) * sqrt(h) 的曲线
结果就是全球分布且实际上随机的采用过程,不需要任何注册中心的协调。举一个实际例子:假设两个应用都依赖`[email protected]`。一个在4小时后安装,另一个在5天后安装,所有人都在14天内安装完毕。恶意版本首先通过随机的全球子集传播,而不是跟随太阳移动。代价是对于新发布的版本(尤其是低下载量的包)收敛速度较慢。但冷却期也有同样的代价;分阶段发布只是更公平地分配了它。
另外需要特别注意,本提案有意改变的是项目*何时*采用制品,而不是*采用哪个*制品。一旦版本选定,现有的锁定文件和可重现性保证仍然有效。安全修复仍然需要不同的发布策略。
## 下一步 (https://illegalcode.net/rfcs/phased_rollouts.html#what-comes-next)
我想过一些可能把这个想法搞复杂的方法:金丝雀报告的公钥证明日志?群体感知工具?跨生态的哈希约定?这些都很酷,但我不想从已经付出的英雄般的努力中转移注意力,比如:
- 能力沙箱
- SBOM
- 运行时监控
- 阅读差异
总结一下,冷却期降低了风险,但并没有消除“总得有人先上”这个事实。行业其他部分已经学会了使用分阶段发布。包生态也应该学到同样的教训。
https://illegalcode.net/rfcs/manual_programming.html
https://illegalcode.net/hacks.html
https://illegalcode.net/rfcs/manual_programming.html
https://illegalcode.net/hacks.html
相似文章
Dependency Cultures - Richard Feldman (Software Should Work Conf 2026)
Richard Feldman 通过对比不同编程语言网站和游戏的依赖图,指出大部分依赖选择是文化规范而非技术必要性。
@github: 一打 Dependabot 拉取请求在周一早上出现,这就是重要更新被忽略的方式。在 Microsoft 的 GCToolkit 上,ro…
本文解释了如何配置 Dependabot 来对依赖更新进行分组,减少拉取请求噪音,同时保持安全性,以 Microsoft 的 GCToolkit 为例。
Dependabot 版本更新引入默认包冷却期
Dependabot 现在在打开版本更新 PR 前会等待三天,以降低供应链攻击的风险。安全更新仍然是即时的。
GitHub 不应成为在 crates.io 上发布 Rust 的依赖条件
一篇讨论在 crates.io 上发布 Rust 包时对 GitHub 的依赖的文章,主张这种依赖不应是强制性的。
引用 GitHub Changeling
GitHub 的 Dependabot 现在默认在开启版本更新拉取请求之前有一个三天的冷却期,无需配置。