摘要

  • RFC 1542 要求中继器把同一客户端的 BOOTREQUEST 发往同一目的端或同一组目的端。
  • 文档用轮询式负载分配说明风险:同一客户端相邻两次请求可能被送到不同服务器。
  • 按客户端身份稳定分流,仍可在多台服务器间分配客户端,同时保留每个客户端的会话路径。

广播请求如何找到远端服务器

BOOTP 面向一类特殊场景:机器刚启动时,可能既不知道自己的 IP 地址,也不知道提供启动信息的服务器在哪里。1985 年发布的 RFC 951 将地址确定和启动文件选择描述为启动过程的第一阶段。客户端可以在本地链路广播请求;如果服务器位于另一张网络,这个广播不会仅凭普通 IP 路由自动变成发往服务器的请求。

RFC 951 因而允许相互配合的网关转发 BOOTP 请求。这项能力是可选的,既可放在网关上,也可由连接客户端网络的另一台转发代理提供。代理收到 BOOTREQUEST 后,在 giaddr 为空时填写接收接口的地址,并递增 hops;服务器随后可以利用 giaddr 把回复送回客户端所在网络。早期规范提出了机制,却没有充分限定中继代理的具体行为。

1993 年 10 月,RFC 1532 尝试补充 BOOTP 的说明。同月发布的 RFC 1542 更新 RFC 951,并取代 RFC 1532;它解释说,RFC 1532 的编辑过程引入了错误。RFC 1542 的摘要明确把中继代理行为列为需要澄清和加强的部分。这意味着中继不再只是“帮忙转发”的设备功能:它的选择方式可能决定客户端与服务器能否完成一组相互关联的消息交换。

每个客户端都要保持目的端亲和性

RFC 1542 把部分运行决定留给网络管理员。中继功能必须能够配置为启用或停用,默认状态必须是停用。中继器必须丢弃 hops 超过 16 的请求,并应允许管理员设置更低阈值。如果 giaddr 为零,中继器必须填入接收请求的接口地址,递增 hops,并保留其余 BOOTP 字段。转发目的端或目的端集合也由配置决定。

在这些配置空间内,规范明确了一条边界:同一客户端的所有 BOOTREQUEST 都必须转发到相同的目的端或目的端集合。RFC 1542 的讨论给出了原因。它提到至少有一种已知的中继实现采用轮询方式分摊负载:每来一个新请求,就转给列表中的下一台 BOOTP 服务器。同一客户端连续发出的请求因此可能落到不同服务器上。

问题并不是使用多台服务器,而是每个数据包都重新选择服务器。当协议需要多轮请求和回复时,按包轮询可能把同一段对话拆开。RFC 1542 指出,这种做法与依赖多次交互的 DHCP 及其他 BOOTP 变体配合不佳。如果一台服务器看到了前一条消息,另一台收到了后续请求,服务器端可能缺少继续处理所需的上下文。规范描述的是协议风险;它没有记载具体故障,也没有说明这种实现有多普遍。

规范同时给出了仍能分摊负载的办法。中继器可以对客户端的链路层地址或其他可靠身份信息计算哈希,并据此选定稳定的服务器或服务器组。这样,不同客户端可以分布到多个目的端,而同一客户端的请求仍沿着相同路径转发。最简单的方案则是把所有请求发给同一个目的端集合。两种方案都把负载分配的单位从“每个数据包”改成了“每个客户端”。

规则的边界与后续语境

RFC 1542 不保证服务器可用、服务器之间共享状态,也不保证客户端最终启动成功。它只约束中继器对同一客户端连续请求的目的端选择。它也没有要求所有客户端必须使用同一台服务器:可以配置多个目的端,也可以用稳定映射把不同客户端分开。

同样发布于 1993 年 10 月的 RFC 1534 说明了 BOOTP 与 DHCP 参与者如何在特定条件下互通;DHCP 消息沿用了 BOOTP 的消息格式。1997 年的 RFC 2131 则更完整地写出 DHCP 的多阶段流程:客户端发现服务器、接收报价、选择服务器并继续发送请求。这些文件帮助理解为何一次启动可能需要多轮通信,却不能据此断言 RFC 1542 描述的轮询行为曾造成某起生产事故。

RFC Editor 为 RFC 1542 登记了一条已核实的勘误:第 3.1.1 节广播标志说明中的一个 BOOTREPLY 应改为 BOOTREQUEST。它与本文讨论的第 4.1.1 节目的端亲和规则无关,也没有改变这条规则。

这段协议史留下的是一条具体的运行边界:把不同客户端分配给多台服务器可以兼容协议;对同一客户端的每个数据包轮流改换目的端,则可能拆散一段多阶段对话。RFC 1542 把这条边界写进规范,同时让网络管理员决定是否开启中继以及采用何种稳定分流方式。

来源