我最近的项目之一使我更加参与了
Aeron项目。 如果您不了解Aeron,请前往 Github网站并进行检查。 它的核心是可靠的消息传递系统,该系统可以在UDP,组播UDP和IPC上运行。 它还包含用于记录和重放的归档功能,以及(仍在积极开发中)用于集群的Raft协议的实现。 我是否提到过它也很快 。
在过去的几周中,我一直沉迷于Aeron进行流量控制的各种策略中。 具体修改现有的流控制策略,并在每个通道的基础上添加更灵活的配置。 在开始之前,先介绍一下背景知识会很有用。
什么是流量控制?
在分布式系统中,流量控制的目的是限制发送方的速率,以免超出相关方的接收方。 UDP没有任何形式的流控制,因此很容易创建发送方,使其超出接收方的速度,从而导致消息丢失。 有多种不同形式的流量控制 ,但我将重点介绍
TCP和Aeron使用的滑动窗口流控制协议 。 滑动窗口协议要求发送方维护数据缓冲区(称为窗口)。 该窗口的大小通常将作为协议的一部分从接收方传递到发送方。 对于像TCP这样的双向协议,窗口的大小在每个TCP段头中传递。 这是发送方在必须等待直到收到确认之前可以发送给接收方的数据量。 如果接收方的应用程序线程繁忙且未从套接字读取数据,并且发送方继续进行传输,则窗口大小值将减小直到达到0,此时发送方必须停止并等待确认。非零窗口大小,然后再次发送。 围绕流量控制窗口的大小,还有很多网络理论,以便充分利用网络。 但我会将其留给读者练习。
Aeron和UDP单播与TCP非常相似,但是Aeron是单向协议,接收方发送状态消息以向发送方指示已准备好接收数据以及准备接收多少数据。 状态消息指示订户在哪里使用针对特定信道/流/会话三元组的消费期限id和消费期限偏移。 接收器窗口值是在发送器需要停止并等待新的状态消息(指示接收器能够使用更多数据)之前可以从该位置发送的数据量。 接收器窗口的大小最大为项大小的1/4,至少为MTU(最大传输单位)的大小。
但是,Aeron的一项简洁功能是它支持多播(以及适用于相同规则的多目标广播),其中同一出版物有多个接收者。 在这种情况下,我们如何确定应将哪些值用于流量控制窗口? 这个问题没有一个正确的答案,因此Aeron提供了许多配置选项,也可以插入您自己的策略。
实际上,Aeron是唯一支持带有动态流控制(我们知道)的UDP多播消息传递的工具。
最大流量控制
最简单,最快的组播流控制形式是一种策略,其中我们将所有接收者都放在最大位置,并使用该值得出发送者可用于发布的限制。 这意味着任何跟不上最快速度的接收器都可能落在后面,并遭受数据包丢失。
最小流量控制
这与最大流量控制策略相反,在该策略中,我们采用所有可用接收器中的最小值。 这样可以防止速度较慢的节点(只要它们仍在发送状态消息)就不会落后。 但是,此策略确实存在这样的风险,即较慢的节点会通过引起背压使发布者变慢来阻止其他接收者。 因为此策略需要跟踪所有单个接收者及其位置,所以它还必须处理节点完全消失的情况。 例如,它已关闭或崩溃。 这是通过超时(默认2s,但可配置)来处理的。 如果在该时间段内未看到接收者的状态消息,则将该接收者从流控制策略中弹出,并允许发布者继续前进。
标记流控制(以前称为“首选流控制”)
标记流控制是一种尝试减轻最小流控制策略的不足之处的策略。 它通过使用最小流量控制方法工作,但仅适用于标记为包含在流量控制组中的接收器子集。 最小流量控制策略是该策略的特例,在该策略中,所有接收者都被视为属于该组。
配置流控制
Aeron 1.26.0附带的一项新功能是能够直接从通道URI控制流控制策略的功能,从而可以对每个发布和订阅进行精细控制。 还可以在媒体驱动程序上下文中指定默认值。 在发布方面,可以将通道指定为:
// Publisher
aeron:udp?endpoint=224.20.30.39:24326|fc=max // max strategy
aeron:udp?endpoint=224.20.30.39:24326|fc=min // min strategy
aeron:udp?endpoint=224.20.30.39:24326|fc=tagged,g:1001 // tagged strategy, group 1001
// Subscriber
aeron:udp?endpoint=224.20.30.39:24326|gtag=1001 // tagged subscription
出版物的最小和最大流量控制设置是最简单的,但是标记的开始变得有点有趣。 ,g:1001指定组标记为1001,并且任何想要参与此发布的流控制的接收器都需要指定该组标记。 订阅频道URI显示了如何确保接收方发送适当的组标记,以便将其包含在发布者流控制组中。
标记流控制策略对于从存在许多具有不同可靠性要求的不同类型订户的信道接收中确实有用。 一个很好的例子是,事件流需要通过网关服务发送到用户(可能是通过HTTP发送给用户),并且还需要传递到几个归档服务以将数据冗余地存储在数据库中。 网关节点可以通过向用户报告错误或重新请求数据来轻松处理消息丢失。 但是,归档服务节点可能无法这样做。 在这种情况下,发布将指定标记的流控制策略,并且归档服务上的订阅将使用
gtag参数以确保它们包含在流控制组中。 网关服务可能会离开 gtag值未设置,并且不会影响发布者上的流控制。
尽管能够将重要的订阅者仅包括在流控制组中,以免发布者超出它们,这很有用,但仍然存在问题。 如果我们的两个归档服务都发生故障,则最终它们的接收器将超时并从组中删除。 如果我们可以要求一个组包含一定数量的标记接收者,然后该出版物可以报告它已连接,那不是很好。 这样,我们可以确保在开始发布数据之前,归档服务节点已启动。
基于流控制的连接
事实证明,现在通过1.26.0发行版也可以做到这一点。 对于标记流控制和最小流控制策略,我们可以指定在认为发布已连接之前必须满足的组最小大小。 这与需要有一个连接的订户的要求无关。 因此,该组最小大小的默认值为0。与策略和流控制组一样,可以在通道URI上指定组最小大小。
aeron:udp?endpoint=224.20.30.39:24326|fc=min,g:/3 // group min size 3
aeron:udp?endpoint=224.20.30.39:24326|fc=tagged,g:1001/3 // group min size 3
在这两种情况下,组的最小大小都设置为3。对于最小流控制策略,我们将需要至少3个连接的接收器,对于标记流控制策略,我们将需要至少3个带标签1001的连接接收器,以及任何不带标签的接收器标签被忽略。
超时时间
通道URI配置上可用的最后一项新功能是能够为分钟流和标记流控制策略指定超时时间。 如前所述,该值默认为2s,但可以设置为任何值。 指定此值时应格外小心,如果该值太短,则接收器可能会在正常运行期间频繁超时。 状态消息每100毫秒发出一次,因此任何短于该时间的消息将无用。 接收器太长且发生故障可能会导致发行商的重大背压失速。 将此设置为最小流量和标记流量控制策略:
aeron:udp?endpoint=224.20.30.39:24326|fc=min,g:/3,t:1000ms // timeout 1s
aeron:udp?endpoint=224.20.30.39:24326|fc=tagged,g:1001/3,t:1s // timeout 1s
摘要
如前所述,使用流控制为多播消息传递总线提供动态背压的想法是Aeron的独特而强大的功能。 能够在每个出版物上配置这些设置可提供更高级别的灵活性,以帮助我们的用户构建所需的系统。 有任何问题,请过来
奇特频道和我们聊天。
翻译自: https://www.javacodegeeks.com/2020/03/flow-control-in-aeron.html