摘要

  • RFC 5351 描述的 RSerPool 把逻辑 pool handle 解析为一个或多个 Pool Element,并通过 ENRP 在服务器之间维护 handlespace。这个同步对象是成员与选择信息,不是应用数据库、事务日志或用户会话。
  • 故障后得到另一个候选地址,只能证明发现链继续工作。旧请求是否提交、新节点是否拥有相容且足够新的状态、重复请求是否安全、原授权是否仍有效,都属于应用层证据。
  • 可审计的恢复链必须分别保留:作用域、成员登记、候选选择、即时可达、应用身份、旧操作提交边界、状态真实性与新鲜度、重试规则、持久执行以及外部结果。

一致的 handlespace 只回答成员问题

RFC 5351 把若干提供相同应用功能的服务器称为一个 pool,每台服务器是 Pool Element。元素通过 ASAP 向 Home ENRP 注册;Pool User 用 pool handle 查询,得到一个或多个可联系的地址。

ENRP 服务器之间交换成员变化并维护分布式名录。Presence 消息携带与本地负责成员相关的校验信息;发现不一致后,可以请求相应部分重新同步。某台 ENRP 失效时,其余节点协商接管 Home ENRP 职责。

这些机制解决了重要问题:名录服务本身不能成为单点故障。但它们同步的仍是 handlespace。一个成员出现在所有 ENRP 视图中,不表示其订单库、会话上下文、授权缓存和最近写入也已经一致。

如果运维界面只显示“ENRP 同步正常”,很容易让人把控制面一致性当成业务连续性。更准确的表述应当是:候选发现所依赖的成员视图已达到协议定义的一致状态;应用复制需要另一套收据。

时间窗口没有因同步而消失

分布式名录无法消除观测与使用之间的时间。Pool Element 可以刚刚回复 keep-alive,随后进程崩溃。注销可能正在传播。新成员可以完成登记,却仍在加载数据或等待迁移结束。

RFC 5352 还允许 endpoint 缓存解析结果。每个缓存项有 stale 定时器。命中过期项时,实现可以一边返回旧信息一边更新,也可以阻塞等待;尚未过期时,通常直接使用缓存。

“未过期”是本地政策对年龄的判断,不是物理世界对存活的证明。即使每次都重新查询,服务器也可能在响应后失效。协议只能明确不确定性的窗口,不能取消它。

因此故障记录必须包含解析时间、缓存年龄、阈值、响应 ENRP、候选全集、实际连接时间和结果。缺少这些字段,“名录正确但现实已变化”会被误判成名录错误,或者反过来被包装成服务成功。

作用域限制防止名称获得虚假权威

pool handle 是有限运营作用域内的唯一字节串。RFC 5351 明确说 handlespace 是平坦且有限的,协议文档当时不处理 handle 的行政管理。RFC 3237 也把跨命名空间互操作留给其他机制。

这意味着成功解析只能证明被查询的 RSerPool 实例理解该名称。它不能证明另一管理域使用同一语义,也不能把一个域的成员授权带到另一个域。

Pool User 与 Pool Element 之间的应用协议同样不由 RSerPool 定义。规范假设双方已通过独立配置支持共同协议。版本、功能、数据格式、租户与访问策略,都不能由 handle 自动推导。

有限作用域并非缺陷,而是清晰的权限边界。共享层负责最少的候选协调;越过边界时,身份、信任、数据与授权必须重新建立。

选择政策排列候选,不预言完成

RFC 5356 定义轮询、加权、随机、优先级以及按负载选择等政策。这些规则让 ENRP 和 Pool User 可以按同一方式处理成员集合。

其中“负载”虽有标准数值范围,含义却由应用决定,并且不在 RSerPool 范围内。同一 pool 的成员必须采用相同定义,但不同 pool 可以统计用户数、CPU、内存或其他资源。

一个最低负载节点仍可能缺少最新数据、被数据库锁阻塞、没有某租户密钥,或无法安全接续旧事务。数值是政策输入,不是未来完成率。

审计系统应保存政策类型、输入时间、负载定义、候选列表与最终选择。如果只留下获胜地址,事后无法判断问题来自节点故障、陈旧指标,还是指标本身没有覆盖真正瓶颈。

找到替代节点没有确定旧请求的命运

RFC 5351 用类似 GETPRIMARYSERVER 与 GETNEXTSERVER 的例子说明:应用可以用 handle 替代固定的主、备地址;发现原服务器失败时,报告失败并取得下一地址。

这个过程没有回答最难的问题:旧请求停在哪一步。请求可能未到达、到达但未提交、已提交但响应丢失,或者已提交但状态尚未复制。四种情况在客户端看到的现象可能都是超时。

若直接向新节点重发,第一种情况需要重试,第二种通常可重试,第三种可能造成重复,第四种还可能让新节点依据落后状态作出错误判断。

规范因此明确指出:依赖应用状态或事务状态的 failover,通常无法在缺少应用知识时定义。RSerPool 提供的是通用钩子,不是通用提交协议。

不透明 cookie 是载体,不是结论

Pool Element 可以周期性发送 cookie,Pool User 只保留最后收到的一份,并在 failover 时交给新元素。对用户而言,cookie 没有可解释结构。

这种设计让基础层无需理解每个应用。但“最后收到”不等于“服务器最后生成”,更不等于“覆盖最后提交”。故障可能发生在提交之后、新 cookie 发出之前。

RFC 5351 建议旧元素签名,新元素验证;RFC 5352 把验证细节留在范围之外。签名可以证明在既定密钥信任下的来源与完整性,却不能证明内容完整、新鲜、版本相容或允许执行。

cookie 与 business card 支持也并非所有角色一律强制。成员身份不能被当成状态迁移能力。上线前必须单独验证格式版本、密钥轮换、过期规则、回滚和跨版本恢复。

优雅注销揭示了两种状态

RFC 3237 要求 Pool Element 注销后不再接收新连接,但可以继续服务注销前已建立的连接。这使排空成为可能,也明确区分了成员资格与在途工作。

名录里已经不存在的元素,仍可能处理重要会话。若编排系统看到注销完成就立即终止实例,会破坏协议希望保留的连续性。

反过来,已经注册的元素也不一定已准备好接收所有业务。它可能仍在预热缓存、追赶复制或等待策略下发。登记是候选资格,应用 readiness 是另一道门。

安全部署需要同时跟踪“是否接受新会话”和“旧会话是否结束”。把两者压成一个布尔状态,是许多所谓无损切换失败的根源。

SCTP 路径切换与跨服务器恢复不同

RSerPool 的若干关系使用 SCTP。SCTP 的多宿主与心跳可以在同一关联、同一对端内切换网络路径。RFC 9260 后来取代 RFC 4960,相关扩展与 API 继续改善传输能力。

选择另一个 Pool Element 则跨过了服务器边界。传输关联、进程内存、应用会话和持久状态可能全部不同。网络路径恢复不能自动搬运这些对象。

监控若只写“failover 成功”,就无法知道发生的是路径变更、关联重建、元素重选、状态恢复,还是仅仅建立了一条新连接。每种事件对应不同风险和验证方法。

对需要 exactly-once 或严格顺序的业务,必须由应用定义操作标识、提交收据、去重窗口与补偿。传输层和 pool 层都不能替它做决定。

成员认证不能继承为业务授权

RFC 5355 分析伪造登记、恶意 ENRP、解析欺骗、重放与拒绝服务,要求参与者之间进行认证和授权,并在单一管理域模型下描述 TLS 与预共享密钥。

这些控制保护名录:谁能加入、谁能回答、消息是否被篡改。它们不意味着最终用户获得了读取数据、转移资金或修改配置的权限。

基础设施主体、应用主体与状态迁移主体至少是三项决定。新节点必须重新确认用户身份与操作权限;旧会话的安全上下文可能需要搬迁或重建。RFC 3237 把安全上下文共享放在 RSerPool 范围之外。

把 pool 成员资格当作业务授权,会让高可用机制成为权限绕过通道。可用性路径应与正常访问控制使用同样严格的证据。

十张收据构成真正的恢复链

第一张是 handle 在正确作用域内存在。第二张是成员出现在所查询名录。第三张是解析或缓存按已知政策返回候选。第四张是当前传输可达。第五张是应用协议相容并认证正确主体。第六张是旧操作状态已知。第七张是迁移状态真实、新鲜、完整且相容。第八张是重试满足幂等与顺序。第九张是效果已持久化。第十张是外部观察确认结果。

ENRP 同步主要支持前几张;它没有失败,只是没有承诺后几张。将每张收据留在正确层级,既避免夸大协议,也能更快定位事故。

IANA 的 RSerPool 表登记消息类型、参数、错误与选择政策。它证明符号可互操作,不证明当下部署、成员健康或业务完成。

Lu Heng 关于最小初始规范与现实层次的文章在这里是披露的分析镜头,而非协议史料:共享名录是符号层,事务与结果属于运行层。RFC 与 IANA 才承担事实依据。