摘要

  • RFC 1546 让一个地址代表由多台主机提供的服务,目标是把报文送到至少一台、最好仅一台服务器,而非证明唯一接收者。
  • 同一目的地址的后续报文可以转到另一台服务器;会话黏性、副本一致性和一次性执行都必须由别的机制承担。
  • 后来的 RFC 细化了服务地址、任播节点和实例标识,却始终没有把共享定位符升级为主机身份或授权凭据。

把一次投递写成一条时间线

1993 年 11 月,Craig Partridge、Trevor Mendez 与 Walter Milliken 发布 RFC 1546。文件来自 IRTF,状态为 Informational,描述的是一项实验性服务,不是互联网标准,也不是某个产品已经部署的证明。

它回答的问题很克制:如果用户只想获得某种服务,而不在意是哪一台服务器提供,互联网能否代替用户选择?答案是给这组服务成员共用一个任播地址,让网络尽力把一个数据报交给至少一台接受该地址的服务器,并且最好只交给一台。

“最好”二字保留了普通 IP 的事实。数据报可能重复,也可能误投。因此,发出一份请求不等于取得了“恰好一台服务器执行一次”的收据。RFC 1546 只规定最低限度的共同语义,把具体路由、成员选择和应用行为留给不同实现。

这项安排改变了地址的指代对象。地址不再是对一台主机的承诺,而是对一项可由多个成员承接的服务的入口。它没有说明哪条路会胜出、哪台机器会收到、进程是否健康、副本是否最新,更没有说明回答者是否有权代表这项服务。

第二个数据报暴露了身份缺口

RFC 1546 用 X 和 Y 两台服务器说明问题。第一个数据报可能到达 X。第二个数据报即使目的地址完全相同,也可能继续到 X,或者转到 Y。IP 层不会记住上一次的选择。

对无状态、一次完成的查询,这可以是优点。对跨报文保存状态的应用,它却会立即改变结果。X 保存的挑战值对 Y 不存在;X 开始的事务不一定在 Y 留有记录;一次未见回复的写入若被重试,不能因为换了实例就推断第一次没有生效。

更严格地说,同一个数据报也可能被多台服务器接收。于是日志里的“客户端只发了一次”不能证明外部效果只发生一次。要得到这样的结论,必须另有事务标识、幂等约束、应用结果或外部观察。

这里至少有九个不能合并的阶段:服务地址被配置或宣告;某个来源在某个时刻选中一条路;报文落到一台或多台节点;回答实例被识别;传输状态被保留或丢失;副本数据被检查;回答者或数据被认证;应用接受、拒绝、重试或失败;最终效果被记录。稳定的目的字段只覆盖其中很小一段。

TCP 通过换掉指代对象来维持连接

RFC 1546 为 TCP 提出过一个很有解释力的办法:任播地址只用于最初那个不带 ACK 的 SYN。服务器用自己的单播地址发回 SYN-ACK,发起端随后把对端从任播地址改成这台服务器的单播地址。第一次发送是在问“哪一台合适”;连接建立后说的是“就是这一台”。

连续性并非来自共享地址突然拥有了主机身份,而是来自传输层主动改用了更具体的身份。现存资料能够证明这项设计建议,却不能证明它被所有 TCP 实现采用。

RFC 7094 后来重申了传输层风险:若活跃事务的报文因路由变化转到没有该事务状态的新实例,会话可能被重置。测试网络里的路径稳定也不能外推为全球路由条件下的稳定。

使用 UDP 或跨多次 TCP 连接保存状态的应用同样如此。RFC 1546 建议在首次交换中学习服务器的单播地址,之后直接找它。也就是说,应用若需要黏性,就要把需求显式化并留下实例级证据。

从“任播服务器”拆出三个对象

RFC 2101 用标识符与定位符的区分继续澄清这一点。任播地址只能定位一组功能相同系统中的某个成员,永远不能唯一标识一台主机;它在时间上的有效唯一性甚至可能短于一次 TCP 建连。

RFC 4786 又给运营对象分别命名。Service Address 是与服务相关联的 IP 地址;Anycast Node 是一个离散位置中对该地址呈现路径的一组主机与路由器;catchment 则是特定路由状态下会被导向某节点的来源集合。路由根据拓扑和请求来源做选择,不能据此推断地理最近、延迟最低或质量最好。

等价路径也可能破坏表面连续性。若设备按报文而不是按流在通向不同节点的路径之间分担,同一事务的报文会被拆开,客户端看到的目的地址却毫无变化。

服务健康与路由可见性也不是同一事实。RFC 4786 认为条件允许时应让健康状态紧密控制路由宣告。RFC 3258 关于共享单播 DNS 的经验则展示了代价:运营者必须协调区域数据分发与切换,收到错误数据的服务器应停止回答;但一旦 DNS 进程失败就自动撤路由并非普遍建议,因为可靠耦合本身增加复杂度,DNS 还可尝试其他服务器地址。

事后再测,可能测到别人

RFC 4892 指出,一次 ping、TCP 连接、traceroute,甚至一条稍后发出的 DNS 查询,都可能到达与原回答不同的服务器。诊断发生在另一个时刻,它证明的是另一次选择,不能替代原事件的实例证据。

RFC 5001 的 EDNS NSID 选项把证据放回被归因的回答中。解析器可以请求一个不透明标识,服务器在同一份 DNS 响应里返回它。这比事后探测更能区分实例,但权限仍然有限:NSID 由服务器定义,不能传递;它不认证运营者、地理位置或数据集,也不证明应用最终做了什么。

因此,可信记录应同时保留时间、服务地址、观察到的路由或 catchment、响应内实例标识、传输结局、数据校验、认证结果和应用效果。每一份收据只能支撑与其权限相符的句子。

恶意成员从来不是后来才想到的问题

RFC 1546 的安全考虑已经警告,恶意主机可以主动声称自己服务于该任播地址并截走流量,窃听者也可能用错误信息抢答。仅凭“报文到达了这个地址的某个成员”无法验证成员资格。

路由能决定报文去哪,却不能授权回答者、证明副本同步或宣布结果成功。认证协议、签名数据、一致性检查、事务收据和独立观察必须分别完成这些任务。

RFC 7094 给出的稳健模式正是承认这条边界:假定同一目的的报文可能落到不同实例;优先使用一个报文即可自足完成的请求、无状态传输、回到单播来源的响应、不跨请求保存硬状态,以及幂等重试。多报文调用若不可避免,可先以任播发现实例,再切到单播。

1993 年留下的不是“最近服务器”神话

RFC 7094 把 RFC 1546 称为第一份正式任播规范,并认为原作者已捕捉到后来持续存在的大部分问题。它真正留下的不是任播必然更快、更安全、更可用的承诺,而是一条清楚的最小规范:地址可以表达服务级选择,连续性与权威则必须另行构造。

本文所依据的资料证明的是公开架构记录。它不证明任何具名部署、漏洞、故障、采用比例、TCP 建议的普遍实现或量化影响。可以确定的是,只保存共享地址会永久丢失回答实例。地址多年不变,并不能在路由切换后复原当时那台服务器。

来源