跳到主要内容

25% 的请求丢了,报表上写着 0% 失败率

小周
小周

· 阅读约 6 分钟

刷 dev.to 连着刷到两点多,一条标题里带"删了 18 万行"的把我钉住了。点进去,作者 Yash Kumar Saini,快两周前发的周报。

这期破一次自己的例,不给 owner/repo 报幕。主角不是某个仓库,是一个人一周的 commit 记录:十几个仓库,102 次提交,净删约 18.8 万行。

但我想讲的不是那 18.8 万行。

先说 breakscale。他那儿开了 Issue #51:节点 25% 的请求因为超时丢掉了,面板上的失败率还是 0%。超时没被算进失败——系统根本不知道自己丢了东西。一头在漏,另一头的表针不动,还挺稳。

PR #57 把超时正确地算进失败率。就这样。

我在这条上停了最久。它反人性。25% 的超时真被算成失败,仪表立刻难看;不算,就一直是 0%。大多数人卡在这个位置的处理方式是调告警阈值,或者给超时另开一个没人看的指标。把一个"看起来健康"的数字亲手修成"看起来不健康",这动作跟技术难度没关系。

同一个 repo 里还有一条我更服的,PR #54:验证器拒绝一个已保存的设计之后,下一次保存或者删除会顺手把它从存储里清掉。修完,就算当前这个 build 打不开这个设计,它也还在。拒绝不等于删除——这区分看着像常识,我在自己碰过的项目里见过太多"校验失败就当垃圾处理"的路径。

这两条是一类活:把"看着没事"改成"知道出事了"。

py-libp2p 那边。Issue #1485:Swarm 关闭的时候泄漏已经拨号的连接 socket,根子在 service-manager 的停止路径没清干净。紧接着 #1487,muxer 的连接测试夹具里留着同一个泄漏。PR #1486 在关闭时显式把连接关掉,把 socket 还给操作系统。

评论区值得单独拎出来。Reid Marlow 在底下解释了这类东西为什么反复出现:如果传输层的清理靠事件循环退出、或者等对象被销毁,而不是显式去 drain 状态机,socket 就很容易在两次测试夹具之间卡在 CLOSE_WAIT。他给的做法是在 service-manager 停止时加一个带硬超时的显式关闭。这段我看了两遍。判断一个项目有没有活人,我不看 commit 数字,看有没有人愿意在一个 issue 里把根因拆到这个粒度。

他还在跑 WebRTC-Direct 的互操作测试,发现 Python 和 Go 两个实现 ICE 握手成功之后连接立刻被掐断。Reid 猜的方向是 DTLS 角色协商和 ALPN 的线上前缀。他说自己遇到过一次类似的:Go 那边因为 Python 默认发 actpass 直接拒了握手,期待的是显式的 active 角色。作者回了一句,问他在别的开源项目里有没有撞见过同样的坑。

这个来回我挺喜欢。

现在说回那 18.8 万行。绝大部分来自一件事:他在自己的 obsidian-vault 里停止追踪 Obsidian 的内部 UI 状态和插件噪声,一次删掉约 17.9 万行,git 历史和同步都干净了。

这里我得泼一盆自己的冷水:删得多不等于厉害。这 17.9 万行里没有一行是功能,全是被插件写进去的噪声,任何一个 vault 用久了的人迟早要做这一步,区别只在于你什么时候受不了。让我多看一眼的不是那个数字,是他删掉的东西不产生任何行为变化,纯赚。

顺手扫一眼他这周还干了什么,密度有点吓人:作品集的 app/projects 和 components/common 清了旧的 catalogue-numbering 界面元素,每个项目行改成独立卡片;canonical origin 换到 yashksaini.vercel.app,修一个 SEO 上的问题;加了 spotlight 区把 GitBanner 和 Reachable 顶上去。Neovim 那边把快捷键参考按前缀树重做了一遍,修掉 <leader>bd 会留个空白窗口的毛病,让终端能从非 normal 窗口打开。Rust 编译器 PR #162123,目标是 -Znext-solver 下报未满足的 opaque item bounds,而不是报成泛型类型不匹配。Agent Orchestrator 的 PR #4717 让解析后的模型在元数据合并里保留下来,修掉 ao spawn 记成空模型。Sixb 的 PR #478 把项目模型目录加进了 core 和 server。

TypeScript 写前端和 CLI、Python 写 libp2p 的网络逻辑、Rust 写编译器,中间还在 Learning-2026 仓库写了个 C++ 打印字母的程序。放平时,这种一人一周换四种语言的状态我会直接判成摊大饼,看着热闹,没一处沉下去。这次我改口。改口的原因就在上面那几个 issue 里——一个肯为 CLOSE_WAIT 去翻 service-manager 停止路径的人,不太可能是在摊。

刷着刷着又跑偏一句:他把日志标题里的顺序编号全去掉了,统一成「Dev log:」开头,还处理了标题里的竖线字符,免得把日志里的 markdown 表格撑坏,连续 7 天提交的记录也还保持着。一边放弃给日志编号,一边保持连续提交,这个组合我觉得挺有意思,虽然可能只是我熬夜熬出来的过度解读。拉回来。

Reachable 那条评论区,Tony Stark 说喜欢他解决 socket 泄漏的部分,觉得 Reachable 本身不错但缺功能和用例。后半句我同意。他这周在 Reachable 里做了可恢复的进度日志、音效评分混音器和帧渲染器,还有一个方便直接粘贴的旁白脚本块,那个是拿来提开发者体验的,他自己也这么说。但项目缺不缺用例,跟我今天推不推他是两件事。

下周他打算继续关 py-libp2p 的 socket 泄漏、把连接关闭逻辑合进去,顺带查 Go 和 Python 的 WebRTC-Direct 为什么互不通,另外多花点时间在 Reachable 的帧渲染器性能上。

不适合谁:想从一篇周报里抄走一个能跑的脚手架的人,别点,这里面没有;想蹲某个新框架速通的,也没有。他这期碰的那些东西,密度全来自他真在维护的那几个仓库。

这期的选手不是仓库,我自己也知道不合规矩,两处破例了——连一行能贴出来装东西的命令都没法给你。能不能打,你把那篇日志从头翻一遍最准。他真把 socket 那条合了,我下期接着写。