TT Lab
开始
学习 学习路径 课程

一个连接变慢,其余全都停住了

运维连接诊断器:预算、原因与回收

在 TT Lab 中继续学习

一句话总结

可用于生产的套接字代码,不仅要能给出成功的字节数,还要能用证据说明终止原因、资源上限,以及取消和异常之后的回收。

为什么需要它

诊断工具运行了十次,每次都有结果。但如果每次运行都会遗留两个 FD,短暂的演示会成功,而长时间开着的运维工具总有一天会失败。反过来,如果把所有错误都归为 timeout,图表看起来也许合理,却无法区分端口拒绝与用户的取消。必须确认,让代码通过的测试,与帮助用户做判断的证据之间,有没有缺漏的条件。

最后这个模块,会把前面学过的连接状态、就绪队列和控制通道整合成一个诊断工具。它不是性能竞赛工具,也不是扫描任意地址的扫描器。课程中的通信只在自己实验环境的 loopback 上重现,不会针对他人的服务器运行。无需添加外部通信和 capability,也能构造出重要的边界条件。

工作原理

上限存在于多个层面。run(limit=8) 把进行中的连接限制为最多 8 个。但是,如果在创建 Dial 时就提前打开了套接字,那么其余等待中的条目也持有 FD。本实验把总列表限制为 128 个,并另外计算两个控制套接字和 selector 的资源。因为 limit 写的是 8,就报告说全部 FD 只有 8 个,是错误的。

Python resource 中的 RLIMIT_NOFILE 是进程可以打开的文件描述符的限额。把它调高并不能解决泄漏。不仅是套接字,还包括文件、控制通道和 selector,都要先调查它们是经由哪些路径打开和关闭的。本课程不会修改主机设置或进程限额,评分器也不会修改或删除学习者的文件。

单独计算执行预算

每一轮只启动 budget 个新连接,也只处理 budget 个完成就绪任务。这是两个独立的计数器。如果只测试所有连接都立即完成的环境,两个预算看起来就是一样的。评分器的确定性调度测试会在前两轮扣住完成事件,然后一次性返回多个。这样,那种限制了启动数量、却把完成队列全部清空的错误代码,也会暴露出来。

输入列表是有限的,所以即使截止时间检查要遍历整个列表,也在这次的上限之内。如果要把这个结构扩展到几十万个连接,还必须评估截止时间堆或定时器结构,以及事件批处理的内存开销。不建议把小型实验中的线性遍历原样用在大规模系统上。

如实汇总结果

每个条目都会留下 connected、failed、timed_out、cancelled 之一,以及 error 整数。connected 的 0 并不是缺失。如果写成 error or 기본값(占位符为默认值)这样,就可能把成功变成“没有信息”。timed_out 是这个诊断工具的截止时间超限,cancelled 是用户的中止。failed 的 errno 是运维人员选择下一步调查对象的线索,但仅凭它并不能断定原因出在防火墙、应用还是网络。

最终汇总会显示总数和四种状态各自的数量,并单独统计失败类 errno 的各自条数。为了不让尚未完成的 pending 悄悄混入成功率的分母,会在汇总输入处拒绝它。这个结果是一次运行的摘要。并没有实现随时间累积的指标或延迟直方图。

证据 确认的内容 无法确认的内容
真实 TCP listen/bind 对照 连接建立的成功与拒绝 TLS、HTTP、业务处理
已满 socketpair 的等待 截止时间与控制唤醒 真实的远程 SYN 丢失
合成的完成事件批次 按轮的预算与就绪队列顺序 内核的公平性保证
注入 close 错误 是否连后面的资源也一并清理 所有操作系统错误的组合

评分器的 PendingSocket 并不是真实连接被延迟的远程服务器。它只是把 connect 的结果以进行中的形式返回,并借助一个已满的本地套接字构造出没有写就绪的条件。在教材中保留这一区分,是为了不把模拟测试的结果夸大为真实的网络验证。

只靠一个 finally 并不够

如果清理循环中第一个 close 抛出了异常,后面的套接字可能就不会被关闭。应当尝试回收每个套接字,保存最初的清理错误,然后把其余的套接字乃至控制通道都清理掉。错误不会被掩盖,而是在最后传播出去。不仅要确认是否返回了正常结果,还要确认失败之后是否没有遗留已打开的 FD。从注册列表中移除时,也要先 unregister,再 close。

在现场相遇的样子

在故障报告中,不要写“测试通过”,而要写明条件。记录目标数量、并发上限、工作预算、成功、拒绝、取消和截止时间超限的数量,以及结束之后 FD 是否被回收。不能仅凭 CPU 较低就说很快,也不能仅凭吞吐量较高就说小请求得到了公平处理。这次的实验是设计生产指标的起点,并不保证真实服务的 SLO 或负载容量。

下一项实验要做什么

在 90 分钟的综合实验中,分 8 个步骤完成连接诊断工具。要同时检查:正确答案是否通过,以及把各项契约逐个破坏的错误答案是否会失败。会话结束后文件会消失,所以请用“+时间”按钮延长时间,并在结束之前把重要的成果另行保存。