连接掉线,又回来了。监控面板重新变绿。可真正恢复的,到底是什么?
这里有两个答案,而且它们并不是同一个说法。要么是原来的传输层扛过了一次中断,要么是某个东西重建了一个替代品,现在由这个替代品在干活。在大多数系统里,无论走哪条路,最终可观测到的状态都一样——已连接、健康、正在服务。但产生这个状态的路径并不相同。
![]()
你的连接越是一次性、越容易被丢弃,这个问题就越紧迫。而现代的设计,恰恰让连接变得非常容易被丢弃。
被当成库存的传输层
对等连接会被重建。连接池里的数据库句柄会被整体丢弃。消费者的分区会被重新分配。租约会过期,然后被另一个进程重新获取。
把传输层当成库存来对待,是正确的做法——正是它让恢复变得廉价。但它也打开了一个缺口:如果承载会话的那个东西随时可能被换掉,那么会话就不是连接本身,就必须有某个东西来说明会话到底是什么。
答案并不光鲜,却承重。一个会话,是一个名字,加上一个单调递增的计数器,再加上一条关于谁来检查它们的规则。
把这件事明确写出来的系统,能得到两样东西:有意义的恢复遥测,以及对一类损坏的免疫力——由已死传输层发出的工作,落到它的替代品上。把这件事留成隐式的系统,两样都得不到,而且这两种失败都是静悄悄的。
三个部分,缺一不可
一个会话要成立,三个部分必须同时在场:
- 一个不依赖当前承载者的名字。
- 一个纪元(epoch)——每次承载者被替换时严格递增的计数器。
- 一个检查者——任何可能被损坏的东西,都拒绝接受盖着更旧纪元戳的工作。
去掉第三个,你得到的只是一种约定,而不是一种保证。而漏掉第三个,恰恰是最常见的情况。
地址不是身份
TCP 用端点地址来标识一条连接。这个选择,正是笔记本电脑从 Wi-Fi 切到蜂窝网络时连接会掉的原因:地址变了,那么按定义它就不再是同一条连接了。身份是从传输层当前的处境推断出来的,而处境变了。
QUIC 的修法值得研究,因为它把整套模式浓缩进了一个决定里。一条 QUIC 连接携带一组连接 ID,按照 RFC 9000 第 5.1 节的说法,“连接 ID 的主要功能,是确保底层协议(UDP、IP)寻址的变化,不会导致某条 QUIC 连接的数据包被投递到错误的端点。”
第 9 节给出了回报:“QUIC 连接并不严格绑定到单一网络路径。连接迁移使用连接标识符,让连接可以转移到新的网络路径上。”同一段还指出,这“允许连接在网络拓扑或地址映射发生变化后继续存在,比如 NAT 重绑定可能造成的那种变化”。
应用从未要求过的地址变化,不再致命,因为身份是被赋予的,而不是被推导出来的。
可推广的部分才是有用的那部分。无论承载你会话的是什么,只要它随时可能被替换,你就得自己说清楚:会话的名字是什么,纪元怎么递增,谁来拒绝旧纪元的工作。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.