任播设计指南
主机上的路由使您能够在服务器主机上直接运行 OSPF 或 BGP。这可以实现一种称为任播的网络架构,其中服务器提供相同的服务,而无需第 2 层扩展或负载均衡器设备。
任播不是新的协议或协议实现,也不需要任何额外的网络配置。任播利用第 3 层网络中固有的 ECMP 功能来提供无状态负载共享服务。
下图描述了任播网络示例。每台服务器都在播发 172.16.255.66/32 任播 IP 地址。

任播架构
任播依赖于第 3 层等价多路径功能,以在整个网络中提供负载共享。每台服务器都宣布一个服务的路由。当路由在网络中传播时,每个网络设备都将该路由视为源自多个位置。当最终用户连接到任播 IP 时,每个网络设备都会对第 3 层和第 4 层标头执行硬件哈希,以确定要使用的路径。
来自最终用户的流中的每个数据包都具有相同的源 IP 地址和目标 IP 地址以及源端口号和目标端口号。网络设备执行的哈希为每个数据包产生相同的答案,确保流中的所有数据包都转到相同的目标。
在下图中,客户端启动两个流:蓝色点状流和红色虚线流。每个流都具有相同的源 IP 地址(客户端的 IP 地址)、目标 IP 地址 (172.16.255.66) 和相同的目标端口(取决于服务;例如,DNS 为端口 53)。每个流都有客户端生成的唯一源端口。

在此示例中,每个流都基于此源端口哈希到不同的服务器,当您运行 ip route show
到目标 IP 地址时,您可以看到这一点
cumulus@spine02$ ip route show 172.16.255.66
172.16.255.66 proto zebra metric 20
nexthop via 169.254.64.0 dev swp1 weight 1
nexthop via 169.254.64.2 dev swp2 weight 1
nexthop via 169.254.64.2 dev swp3 weight 1
nexthop via 169.254.64.0 dev swp4 weight 1
在 Cumulus Linux 交换机上,您可以使用 cl-ecmpcalc
命令查看硬件哈希。在上图中,两个流源自远程用户,目标地址为任播 IP 地址。每个会话都有不同的源端口。使用 cl-ecmpcalc
命令查看会话哈希到不同的出口端口。
cumulus@spine02$ sudo cl-ecmpcalc -p udp -s 10.2.0.100 --sport 32700 -d 172.31.255.66 --dport 53 -i swp51
ecmpcalc: will query hardware
swp2
cumulus@spine02$ sudo cl-ecmpcalc -p udp -s 10.2.0.100 --sport 31884 -d 172.31.255.66 --dport 53 -i swp51
ecmpcalc: will query hardware
swp3
任播与 TCP 和 UDP
任播功能和成本效益的关键组成部分是网络不维护流的状态。Cumulus Linux 通过路由表单独处理每个数据包,从而节省了跟踪单个流所需的内存和资源,类似于负载均衡设备的功能。
流中的每个数据包都哈希到相同的下一跳。但是,如果该下一跳不再有效,则流量将流向另一个任播下一跳。例如,在下图中,如果 leaf03 发生故障,则流量将流向另一个任播地址;在本例中为 server04

对于依赖 UDP 的无状态应用程序(如 DNS),这不会带来问题。但是,对于依赖 TCP 的有状态应用程序(如 HTTP),这会中断任何现有的流量流,例如文件下载。如果 TCP 三次握手发生在 server03 上,则在发生故障后,server04 没有建立连接,并向客户端发送 TCP 重置消息,从而重新启动会话。
任播环境中的 TCP 应用程序具有短生命周期的流(以秒或更短的时间为单位衡量),以减少网络更改或故障的影响。
弹性哈希
弹性哈希提供了一种方法来防止故障影响不相关流的哈希结果。但是,当您添加新的下一跳时,弹性哈希无法防止重新哈希。
硬件哈希函数确定给定流使用哪个路径。该哈希的简化版本是协议、源 IP 地址、目标 IP 地址、源第 4 层端口和目标第 4 层端口的组合。完整的哈希函数包括这些字段以及可能的第 3 层下一跳地址列表。哈希结果通过下一跳地址数量的模数。如果下一跳地址的数量发生变化(通过添加或删除下一跳),这将更改所有流量的哈希结果,包括已建立的流。
在上面的示例中,leaf03 处于故障状态;流量哈希到 server04。这是哈希考虑三个可能的下一跳 IP(leaf01、leaf02、leaf04)的结果。当 leaf03 重新联机时,可能的下一跳 IP 的数量增加到四个。这会更改哈希函数中模数值,从而导致将流量发送到不同的服务器,即使不受更改影响也是如此。
正如您在下面看到的,leaf03 处于故障状态。蓝色点状流使用 leaf02 到达 server02。

当 leaf03 恢复服务时,spine02 上的哈希函数会发生变化,从而影响蓝色点状流

正如设备的添加会影响不相关的流量一样,设备的移除也会影响不相关的流量,因为哈希函数的模数会发生变化。您可以在下面看到这一点,其中蓝色点状流通过 leaf01,红色虚线通过 leaf04。

现在,leaf02 发生故障。结果,spine02 上的模数从四个可能的下一跳更改为三个下一跳。在此示例中,红色虚线重新哈希到 leaf03

为了解决此问题,弹性哈希可以防止流量流在不相关的故障场景中发生偏移。启用弹性哈希后,leaf02 的故障不会影响两个现有流,因为它们不会流经 leaf02

虽然弹性哈希可以防止在下一跳故障时重新哈希,但它无法防止在添加下一跳时重新哈希。
任播的应用
基于 DP 的应用程序非常适合任播架构,例如 NTP 或 DNS。
在考虑在任播场景中部署的应用程序时,首先要回答的两个问题是
- 应用程序是否依赖 TCP 来正确排序数据。
- 应用程序是否依赖于多个会话作为应用程序的一部分。
具有多个连接的应用程序
网络不知道同一应用程序的不同会话之间有任何会话或关系。这会影响依赖多个 TCP 或 UDP 连接才能正常运行的协议 - 例如 FTP。
FTP 数据传输需要两个连接:一个用于控制,另一个用于文件传输。这两个连接是独立的,具有自己的 TCP 端口。如果您在任播架构中部署 FTP 服务器,当辅助数据连接启动时,流量的目标最初是相同的 FTP 服务器 IP 地址。但是,由于端口不同,网络会将此流量哈希为新的唯一流。这会导致新的会话在新服务器上进行。如果 FTP 服务器应用程序能够进行强大的信息共享,则新服务器会接受该数据连接,因为它没有控制会话中原始请求的历史记录。
发起流量和接收流量
不要通过任播 IP 地址启动出站 TCP 会话;从任播 IP 地址发起的流量可能在网络哈希后不会返回到同一任播服务器。对于入站会话,网络哈希对于流中的所有数据包都是相同的,并且入站流量哈希到同一任播服务器。
TCP 和任播
您可以将基于 TCP 的应用程序与任播结合使用,并遵循以下建议
- TCP 会话是短期的。
- 失败的会话或 TCP 重置的影响不会影响应用程序。例如,网页刷新是可以接受的。
- 存在独立于 TCP 会话的应用程序级会话管理。
- 重定向层处理错误哈希的流。
不要将具有较长生命周期流的 TCP 应用程序用作任播服务。例如
- FTP 或其他大型文件传输。
- 您必须完成和记录的事务。例如,金融交易。
- 没有应用程序级自动恢复的流媒体。
结论
任播可以为服务提供低成本、高度可扩展的实现。但是,基于网络的 ECMP 中固有的限制使得任播难以与某些应用程序集成。任播架构最适合无状态应用程序或能够在应用层共享会话状态的应用程序。