通过 MQ 流式传输音频流(可扩展性)
Streaming audio streams trough MQ (scalability)
我的问题比较具体,所以我可以接受一个笼统的回答,这会为我指明正确的方向。
问题描述:
我想将来自多个生产者的特定任务数据传递给处理该任务的特定消费者(两者都是 k8s 中的 docker 容器 运行)。这种关系是多对多的——任何生产者都可以为任何消费者创建数据包。每个消费者在任何给定时刻处理约 10 个数据流,而每个数据流由每 秒 的 100 条 160b 条消息(来自不同的生产者)组成。
当前解法:
在我们目前的解决方案中,每个生产者都有一个任务的缓存:(IP:PORT)对消费者的值,并使用UDP数据包直接发送数据。它具有很好的可扩展性,但在部署中相当混乱。
问题:
这可以通过各种消息队列(Kafka、Redis、rabbitMQ...)的形式实现吗?例如,每个任务都有一个通道,生产者发送数据,而消费者 - 很好地消费它们?为 MQ 处理多少流是可行的(我知道它会有所不同 - 建议你最好)。
编辑:等于每秒 100 000 条消息的 1000 个流是否可行? (1000 个流的吞吐量是 16 Mb/s)
编辑 2:将打包大小固定为 160b(打字错误)
基本方法
从 Kafka 的角度来看,您问题中的每个流都可以映射到 Kafka 中的一个主题,并且
因此每个主题有一对生产者-消费者。
缺点: 如果你有很多流,你最终会得到很多主题和 IMO,随着你增加编号,这里的解决方案也会变得更加混乱。主题数。
另一种方法
或者,最好的方法是将多个流映射到一个主题,其中每个流由一个键分隔(就像您使用 IP:Port 组合),然后让多个消费者分别订阅一组特定的分区(s) 由密钥确定。分区是 Kafka 中的可扩展性点。
缺点: 虽然你可以增加编号。分区数,您不能减少它们。
数据类型很重要
如果您的流是异构的,从某种意义上说,它们不适合共享一个共同的主题,您可以创建更多主题。
通常,主题由它们托管的数据决定and/or他们的消费者如何处理主题中的数据。如果您所有的消费者都做同样的事情,即具有相同的处理逻辑,那么选择一个具有多个分区的主题是合理的。
需要考虑的几点:
与您当前的解决方案(我想)不同,一旦收到消息,它不会在接收和处理后丢失,而是继续保留在主题中,直到配置的保留期。
在确定键控策略时要格外小心,即哪些消息落在哪些分区中。如前所述,如果您所有的消费者都做同样的事情,那么他们都可以在一个消费者组中以分担工作量。
属于同一组的消费者执行共同任务,并将订阅由分区分配器确定的一组分区。然后每个消费者将获得一组密钥,换句话说,一组流或根据您当前的解决方案,一组一对或多对 IP:Port。
除非您需要磁盘持久性,否则甚至不要查看消息代理方向。您只是将一个问题添加到另一个问题上。直接网络代码是解决音频广播的正确方法。现在,如果您的代码很乱,并且您想要一个简化的编程模型,那么套接字的一个很好的替代品是 ZeroMQ 库。这将为您提供您关心的所有 MessageBroker 功能:a) 离散消息而不是流,b) 客户端可发现性;不会过度使用另一个软件层。
说到“可行”:每秒 100 000 条消息和 160kb 的消息是大量数据,即使没有任何消息传递协议,它也达到 1.6 Gb/sec。一般来说,Kafka 在小消息的消息吞吐量方面表现出色,因为它在许多层上对消息进行批处理。知道 Kafka 的这种持续性能通常受到磁盘速度的限制,因为 Kafka 是有意以这种方式编写的(最慢的组件是磁盘)。但是,您的消息非常大,您需要同时写入和读取消息,所以如果没有大型集群安装,我认为不会发生这种情况,因为您的问题是实际数据吞吐量,而不是消息数量。
因为你的数据有限,其他经典的MQ软件如ActiveMQ、IBM MQ等其实也能很好的应对你的情况。一般来说,经典代理比 Kafka 更“健谈”,并且在处理小消息时无法命中 Kafka 的消息输出。但只要您使用大型非持久性消息(和适当的代理配置),您也可以期待 mb/sec 从这些消息中获得不错的性能。经典代理将通过适当的配置直接将生产者的套接字连接到消费者的套接字,而无需访问磁盘。相比之下,Kafka 将始终首先持久化到磁盘。所以他们甚至比 Kafka 有一些延迟优势。
然而,这种直接的套接字到套接字“优化”只是一个完整的循环转向这个答案的开始。除非您需要音频流持久性,否则您与中间代理所做的一切就是寻找一种间接方式将生产套接字绑定到消费套接字,然后通过此连接发送离散消息。如果这就是您所需要的 - ZeroMQ 就是为此而生的。
还有一种称为 MQTT 的消息传递协议,如果您选择寻求代理解决方案,您可能会感兴趣。因为它是一个具有极低开销的可扩展解决方案。
我的问题比较具体,所以我可以接受一个笼统的回答,这会为我指明正确的方向。
问题描述: 我想将来自多个生产者的特定任务数据传递给处理该任务的特定消费者(两者都是 k8s 中的 docker 容器 运行)。这种关系是多对多的——任何生产者都可以为任何消费者创建数据包。每个消费者在任何给定时刻处理约 10 个数据流,而每个数据流由每 秒 的 100 条 160b 条消息(来自不同的生产者)组成。
当前解法: 在我们目前的解决方案中,每个生产者都有一个任务的缓存:(IP:PORT)对消费者的值,并使用UDP数据包直接发送数据。它具有很好的可扩展性,但在部署中相当混乱。
问题: 这可以通过各种消息队列(Kafka、Redis、rabbitMQ...)的形式实现吗?例如,每个任务都有一个通道,生产者发送数据,而消费者 - 很好地消费它们?为 MQ 处理多少流是可行的(我知道它会有所不同 - 建议你最好)。
编辑:等于每秒 100 000 条消息的 1000 个流是否可行? (1000 个流的吞吐量是 16 Mb/s)
编辑 2:将打包大小固定为 160b(打字错误)
基本方法
从 Kafka 的角度来看,您问题中的每个流都可以映射到 Kafka 中的一个主题,并且 因此每个主题有一对生产者-消费者。
缺点: 如果你有很多流,你最终会得到很多主题和 IMO,随着你增加编号,这里的解决方案也会变得更加混乱。主题数。
另一种方法
或者,最好的方法是将多个流映射到一个主题,其中每个流由一个键分隔(就像您使用 IP:Port 组合),然后让多个消费者分别订阅一组特定的分区(s) 由密钥确定。分区是 Kafka 中的可扩展性点。
缺点: 虽然你可以增加编号。分区数,您不能减少它们。
数据类型很重要
如果您的流是异构的,从某种意义上说,它们不适合共享一个共同的主题,您可以创建更多主题。
通常,主题由它们托管的数据决定and/or他们的消费者如何处理主题中的数据。如果您所有的消费者都做同样的事情,即具有相同的处理逻辑,那么选择一个具有多个分区的主题是合理的。
需要考虑的几点:
与您当前的解决方案(我想)不同,一旦收到消息,它不会在接收和处理后丢失,而是继续保留在主题中,直到配置的保留期。
在确定键控策略时要格外小心,即哪些消息落在哪些分区中。如前所述,如果您所有的消费者都做同样的事情,那么他们都可以在一个消费者组中以分担工作量。
属于同一组的消费者执行共同任务,并将订阅由分区分配器确定的一组分区。然后每个消费者将获得一组密钥,换句话说,一组流或根据您当前的解决方案,一组一对或多对 IP:Port。
除非您需要磁盘持久性,否则甚至不要查看消息代理方向。您只是将一个问题添加到另一个问题上。直接网络代码是解决音频广播的正确方法。现在,如果您的代码很乱,并且您想要一个简化的编程模型,那么套接字的一个很好的替代品是 ZeroMQ 库。这将为您提供您关心的所有 MessageBroker 功能:a) 离散消息而不是流,b) 客户端可发现性;不会过度使用另一个软件层。
说到“可行”:每秒 100 000 条消息和 160kb 的消息是大量数据,即使没有任何消息传递协议,它也达到 1.6 Gb/sec。一般来说,Kafka 在小消息的消息吞吐量方面表现出色,因为它在许多层上对消息进行批处理。知道 Kafka 的这种持续性能通常受到磁盘速度的限制,因为 Kafka 是有意以这种方式编写的(最慢的组件是磁盘)。但是,您的消息非常大,您需要同时写入和读取消息,所以如果没有大型集群安装,我认为不会发生这种情况,因为您的问题是实际数据吞吐量,而不是消息数量。
因为你的数据有限,其他经典的MQ软件如ActiveMQ、IBM MQ等其实也能很好的应对你的情况。一般来说,经典代理比 Kafka 更“健谈”,并且在处理小消息时无法命中 Kafka 的消息输出。但只要您使用大型非持久性消息(和适当的代理配置),您也可以期待 mb/sec 从这些消息中获得不错的性能。经典代理将通过适当的配置直接将生产者的套接字连接到消费者的套接字,而无需访问磁盘。相比之下,Kafka 将始终首先持久化到磁盘。所以他们甚至比 Kafka 有一些延迟优势。
然而,这种直接的套接字到套接字“优化”只是一个完整的循环转向这个答案的开始。除非您需要音频流持久性,否则您与中间代理所做的一切就是寻找一种间接方式将生产套接字绑定到消费套接字,然后通过此连接发送离散消息。如果这就是您所需要的 - ZeroMQ 就是为此而生的。
还有一种称为 MQTT 的消息传递协议,如果您选择寻求代理解决方案,您可能会感兴趣。因为它是一个具有极低开销的可扩展解决方案。