当前位置: 首页 > news >正文

Aeron:Multi-Destination-Cast

Multi-Destination-Cast(MDC)是一种功能,允许 Aeron 从单个 Publication 同时向多个目的地传送数据。Multiple-Destination-Cast是 Aeron 的一项高级功能,本指南将介绍如何开发一个简单示例的基本知识。

一、MDC Publications

注:

MDC Publications 能够在不支持 UDP 组播的环境中提供与 UDP 组播大致相同的行为。请注意,这不是真正的组播—数据是单独发送到每个订阅(subscription)的,但支持流量控制功能。

MDC Publications可以动态或手动模式运行。对于动态 MDC Publications,Subscription 会在运行时动态添加到Publications中。对于手动 MDC Publications,Subscription 必须显式添加到Publications中。

动态 MDC Publications的工作方式与标准 Aeron Publications非常相似,但配置是颠倒的。

TypePublicationSubscription
Standardchannel指向Subscription(Channel points to Subscription)Channel/port on localhost
Dynamic Multi-Destination-Cast PublicationChannel/port on localhostchannel指向Subscription(Channel points to Publication)

Sample Dynamic MDC Publication(示例) 

完整的multi-host示例可在 GitHub 上找到。该示例创建了一个具有动态 MDC Publication的单个publisher,以及两个订阅 MDC Publication的客户端。每个进程都位于一个专用的 Docker 容器中。

Media Driver Configuration 

Media Driver不需要任何特定配置,但是,如果您要求 Publications 能够在未连接任何 Subscriptions 的情况下发布数据,则可以选择启用 spiesSimulateConnection。示例代码如下:

final var mediaDriverContext = new MediaDriver.Context().spiesSimulateConnection(true).errorHandler(this::errorHandler).threadingMode(ThreadingMode.SHARED).sharedIdleStrategy(new SleepingMillisIdleStrategy()).dirDeleteOnStart(true);

 Publication

MDC 动态Publication使用特定的通道配置,其中至少包括:

aeron:udp?control-mode=dynamic|control=MDC_HOST:MDC_CONTROL_PORT

control-mode=dynamic 告知 Aeron 这是一个Dynamic MDC Publication。上述示例中的 MDC_HOST 必须是运行该Publication的主机(host)。在幕后,Subscriptions会使用控制端口连接到该主机,以构建运行时流程,因此控制端口必须是客户端已知的端口。

示例代码(sample code)构建Publication channel的过程如下:

final var publicationChannel = "aeron:udp?control-mode=dynamic|control=" + host+ ":" + controlChannelPort;
final var publication = aeron.addExclusivePublication(publicationChannel, 100);

除基本配置外,还可通过通道配置流量控制策略。其中包括基于组限制的流量控制策略,即必须连接最少数量的节点,Publication才会进入连接状态。

Subscription

将MDC Subscription连接到dynamic Publication非常简单—通道配置必须包括 MDC Publication host和远程主机(host)将发布到的本地端点。最小配置如下:

aeron:udp?endpoint=LOCALHOST:0|control=MDC_HOST:MDC_CONTROL_PORT|control-mode=dynamic

与Publication一样,control-mode=dynamic(动态控制模式)告诉 Aeron 这是一个dynamic MDC connection,endpoint=LOCALHOST:0 指的是 MDC Dynamic Publication将向其发布数据的本地主机上的一个短暂端口,也可以是一个预定义端口。最后,control=MDC_HOST:MDC_CONTROL_PORT 告诉 Aeron 如何连接远程动态 MDC Publication。

示例代码( sample code )构建订阅通道的过程如下:

final mdcSubscription = aeron.addSubscription("aeron:udp?endpoint=" + host+ ":0|control=" + mdcHost + ":" + mdcControlPort + "|control-mode=dynamic", 100);

该示例运行两个客户端实例,每个实例位于一个专用的 Docker 主机中。

Sample output

以下是通过 docker-compose up 运行的示例输出,经过简单编辑:

mdc-subscriber-2_1  | 16:47:00.945 [main] INFO MultiDestinationSubscriberAgent - launching media driver
mdc-publisher_1     | 16:47:00.946 [main] INFO MultiDestinationPublisherAgent - launching media driver
mdc-subscriber-1_1  | 16:47:01.066 [main] INFO MultiDestinationSubscriberAgent - launching media driver
mdc-subscriber-2_1  | 16:47:01.082 [main] INFO MultiDestinationSubscriberAgent - connecting aeron; media driver directory /dev/shm/aeron-root
mdc-publisher_1     | 16:47:01.083 [main] INFO MultiDestinationPublisherAgent - launching aeron
mdc-subscriber-2_1  | 16:47:01.093 [main] INFO MultiDestinationSubscriberAgent - adding the subscription
mdc-subscriber-2_1  | 16:47:01.093 [main] INFO MultiDestinationSubscriberAgent - detected ip4 address as 10.1.0.3
mdc-publisher_1     | 16:47:01.093 [main] INFO MultiDestinationPublisherAgent - Media Driver directory is /dev/shm/aeron-root
mdc-publisher_1     | 16:47:01.095 [main] INFO MultiDestinationPublisherAgent - detected ip4 address as 10.1.0.2
mdc-publisher_1     | 16:47:01.107 [main] INFO MultiDestinationPublisherAgent - creating publication
mdc-subscriber-2_1  | 16:47:01.128 [mdc-subscriber] INFO MultiDestinationSubscriberAgent - starting
mdc-subscriber-1_1  | 16:47:01.162 [main] INFO MultiDestinationSubscriberAgent - connecting aeron; media driver directory /dev/shm/aeron-root
mdc-publisher_1     | 16:47:01.165 [mdc-publisher] INFO MultiDestinationPublisherAgent - Starting up
mdc-publisher_1     | 16:47:01.166 [mdc-publisher] INFO MultiDestinationPublisherAgent - appended 1
mdc-subscriber-1_1  | 16:47:01.170 [main] INFO MultiDestinationSubscriberAgent - adding the subscription
mdc-subscriber-1_1  | 16:47:01.170 [main] INFO MultiDestinationSubscriberAgent - detected ip4 address as 10.1.0.4
mdc-subscriber-1_1  | 16:47:01.201 [mdc-subscriber] INFO MultiDestinationSubscriberAgent - starting
mdc-publisher_1     | 16:47:03.167 [mdc-publisher] INFO MultiDestinationPublisherAgent - appended 2
mdc-subscriber-2_1  | 16:47:03.170 [mdc-subscriber] INFO MultiDestinationSubscriberFragmentHandler - received 2
mdc-subscriber-1_1  | 16:47:03.171 [mdc-subscriber] INFO MultiDestinationSubscriberFragmentHandler - received 2
mdc-publisher_1     | 16:47:05.167 [mdc-publisher] INFO MultiDestinationPublisherAgent - appended 3
mdc-subscriber-1_1  | 16:47:05.171 [mdc-subscriber] INFO MultiDestinationSubscriberFragmentHandler - received 3
mdc-subscriber-2_1  | 16:47:05.170 [mdc-subscriber] INFO MultiDestinationSubscriberFragmentHandler - received 3
...

注:

  • 示例使用了宽松的 IdleStrategy 配置,这就解释了为什么在append and receive之间会有 3 到 4 毫秒的间隔。

  • mdc-publisher_1 的日志条目中 appended 1,但两个客户端却没有显示相应的received 1 的日志。这是因为 mdc-publisher_1 Media Driver将 spiesSimulateConnection 设置为 true,而 mdc-subscriber-* 进程尚未连接。它们确实收到了 2。

Flow Control 

上面的例子提出了一个问题:如果 mdc-subscriber-1 开始落后于 mdc-subscriber-2mdc-publisher 应该怎么办?在 Aeron 中可以通过流量控制配置这种行为。可以在Media Driver中将流量控制配置为默认值,然后按通道进行自定义。

Flow Control Types 
TypeDescription
maxPublication将受到最快订阅(Subscription)的限制。速度慢的消费者可能会丢失数据包。这是 Aeron 的默认设置。(Publication will be limited by the fastest Subscription. Slow consumers may lose data packets. This is the default in Aeron.)
minPublication将受到最慢订阅(Subscription)的限制。(Publication will be limited by the slowest Subscription.)
taggedPublication将受到组内最慢标记订阅(Subscription)的限制(Publication will be limited by the slowest tagged Subscription within a group)

如果Publication产生数据的速度超过了流量控制策略规定的水平,Publication就会受到back pressure(背压:实际上就是常规说的堵上游)。 

MAX FLOW CONTROL 

例如,通过在通道配置中设置 fc=max 来配置最大流量控制: 

aeron:udp?control-mode=dynamic|control=MDC_HOST:MDC_CONTROL_PORT|fc=max

或者使用Media Driver Context设置默认值(注意,UDP 组播和多目的地组播(Multi-Destination-Cast)都使用 multicastFlowControlSupplier):

final var mediaDriverContext = new MediaDriver.Context()
....multicastFlowControlSupplier(new MaxMulticastFlowControlSupplier())
...

MIN FLOW CONTROL

例如,通过在通道配置中设置 fc=min 来配置最小流量控制: 

aeron:udp?control-mode=dynamic|control=MDC_HOST:MDC_CONTROL_PORT|fc=min

可设置的其他选项包括组大小。下面的示例用 g:/5 设置了 5 个组。组大小控制着Publication的连接状态—例如,如果组大小为 5,则只有当 5 个Subscriptions连接时,Publication才会被视为已连接。这样,系统就可以在至少有 5 个已连接Subscriptions的情况下运行,其中最慢的Subscriptions将为所有已连接Subscriptions设定速度。

aeron:udp?control-mode=dynamic|control=MDC_HOST:MDC_CONTROL_PORT|fc=min,g:/5

这也可以在Media Driver Context中进行默认设置(此处将组大小设置为 5):

final var mediaDriverContext = new MediaDriver.Context()
....multicastFlowControlSupplier(new MinMulticastFlowControlSupplier()).flowControlGroupMinSize(5)
...

TAGGED FLOW CONTROL

有时,您需要在Multi-Destination-Cast中进行更精细的控制,例如,您可能有一组用户不应该丢失数据包,但您也可能连接了不受数据丢失影响的其他用户,您不希望这些接受数据丢失的用户用最小流量(min)控制策略拖住所有Subscriptions用户。标记流量控制策略可以实现这一点。

以下配置将 Publication 信道的流量控制设置为标记(tagged),组设置为 101

aeron:udp?control-mode=dynamic|control=MDC_HOST:MDC_CONTROL_PORT|fc=tagged,g:101

要让Subscription加入带有 101 标签的流量控制(从而受到流量控制,就像最小策略一样),需要对 gtag 进行如下设置:

aeron:udp?endpoint=LOCALHOST:0|control=MDC_HOST:MDC_CONTROL_PORT|control-mode=dynamic|gtag=101

如果Subscription需要加入同一个 MDC Publication,但不担心数据丢失(即不受流量控制),则可以删除 gtag

aeron:udp?endpoint=LOCALHOST:0|control=MDC_HOST:MDC_CONTROL_PORT|control-mode=dynamic

以下是设置Media Driver默认值的等效方法:

final var mediaDriverContext = new MediaDriver.Context()
....multicastFlowControlSupplier(new TaggedMulticastFlowControlSupplier()).flowControlGroupTag(101)
...

 

与最小(min)流量控制策略一样,标记(tagged)流量控制也可设置最小分组规模。在本例中,标签设置为 101,组大小设置为 5

aeron:udp?control-mode=dynamic|control=MDC_HOST:MDC_CONTROL_PORT|fc=tagged,g:101/5

 See Also

  • Multiple Destinations in the Aeron Wiki
  • Flow and Congestion Control in the Aeron Wiki
  • Flow Control in Aeron by Michael Barker

相关文章:

  • Arduino单片机详解
  • 深入了解Redis的TYPE命令
  • Python启多个线程,运行多个Python文件
  • 力扣191. 位1的个数
  • HTML+CSS+PHP实现网页留言板功能(需要创建数据库)
  • VB点击按钮,改变按钮的文字和字体
  • Java 枚举详解与应用
  • 烟雾自动监测识别摄像机
  • AI 已经在污染互联网了。。赛博喂屎成为现实
  • Canonical Juju 的一个奇怪编排部署
  • 哈喽GPT-4o——对GPT-4o 编程的思考与看法
  • 2024人工智能指数报告(二):技术性能
  • Linux 中断实验
  • 20240619火车头采集器GPT改写插件介绍文档
  • 速盾:使用 CDN 可以隐藏 IP 吗?该怎样应对防御?
  • Apache Pulsar 2.1 重磅发布
  • Koa2 之文件上传下载
  • Laravel 中的一个后期静态绑定
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • Nacos系列:Nacos的Java SDK使用
  • Service Worker
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 工作手记之html2canvas使用概述
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 聊聊directory traversal attack
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 前端技术周刊 2019-01-14:客户端存储
  • 驱动程序原理
  • gunicorn工作原理
  • MPAndroidChart 教程:Y轴 YAxis
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • #Spring-boot高级
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • $.ajax()参数及用法
  • (2024)docker-compose实战 (8)部署LAMP项目(最终版)
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (三)终结任务
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)C#调用WebService 基础
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • **CI中自动类加载的用法总结
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .Net Core 中间件与过滤器