通过 MQ可扩展性流式传输音频流

问题描述

我的问题相当具体,所以我会给出一个一般性的答案,这会为我指明正确的方向。

问题描述: 我想将来自多个生产者的特定任务数据传递给处理该任务的特定消费者(两者都是在 k8s 中运行的 docker 容器)。这种关系是多对多的——任何生产者都可以为任何消费者创建一个数据包。每个消费者在任何给定时刻都在处理大约 10 个数据流,而每个数据流由 100 个每 的 160b 条消息组成(来自不同的生产者)。

当前的解决方案: 在我们当前的解决方案中,每个生产者都有一个任务缓存:(IP: PORT)消费者的值对,并使用 UDP 数据包直接发送数据。它具有很好的可扩展性,但在部署方面相当混乱。

问题: 这可以以各种消息队列(Kafka、Redis、rabbitMQ...)的形式实现吗?例如,为每个任务都有一个通道,生产者在消费者发送数据时发送数据 - 很好地消费它们? MQ 可以处理多少个流(我知道这会有所不同 - 建议您最好)。

编辑:1000 个流等于每秒 100 000 条消息是否可行? (1000 个流的吞吐量为 16 Mb/s)

编辑 2:将压缩大小固定为 160b(拼写错误

解决方法

除非您需要磁盘持久性,否则甚至不要看消息代理方向。您只是将一个问题添加到另一个问题中。直接网络编码是解决音频广播的正确方法。现在,如果您的代码很乱,并且您想要一个简化的编程模型来替代套接字,那么 ZeroMQ 库是一个很好的选择。这将为您提供您关心的所有 MessageBroker 功能:a) 离散消息传递而不是流,b) 客户端可发现性;无需过度使用另一个软件层。

谈到“可行”:每秒 100 000 条消息和 160kb 消息是大量数据,即使没有任何消息传递协议也达到 1.6 Gb/秒。一般来说,Kafka 在小消息的消息吞吐量方面表现出色,因为它在许多层上批量处理消息。知道 Kafka 的这种持续性能通常受到磁盘速度的限制,因为 Kafka 是故意以这种方式编写的(最慢的组件是磁盘)。但是,您的消息非常大,您需要同时写入和读取消息,因此如果没有大型集群安装,我认为不会发生这种情况,因为您的问题是实际数据吞吐量,而不是消息数量。

由于您的数据有限,即使是其他经典的 MQ 软件,如 ActiveMQ、IBM MQ 等,实际上也能很好地应对您的情况。一般来说,经典代理比 Kafka 更“健谈”,并且在处理小消息时无法命中 Kafka 的消息吞吐量。但是,只要您使用大型非持久性消息(和适当的代理配置),您也可以期望从这些消息中获得不错的 mb/sec 性能。经典的 brokers 会通过适当的配置,将生产者的套接字直接连接到消费者的套接字,而不会碰到磁盘。相比之下,Kafka 总是先持久化到磁盘。因此,它们甚至比 Kafka 还具有一些延迟优势。

然而,这种直接的套接字到套接字“优化”只是一个完整的循环转向这个答案的开始。除非您需要音频流持久性,否则您使用中间代理所做的就是找到一种间接方式将生产套接字绑定到消费套接字,然后通过此连接发送离散消息。如果这就是您所需要的 - ZeroMQ 就是为此而设计的。

还有一种称为 MQTT 的消息传递协议,如果您选择寻求代理解决方案,您可能会对它感兴趣。因为它是一种具有极低开销的可扩展性极强的解决方案。

,

基本方法

从 Kafka 的角度来看,问题中的每个流都可以映射到 Kafka 中的一个主题,并且 因此每个主题有一对生产者-消费者。

缺点:如果你有很多流,你最终会得到很多主题,而且 IMO 在这里解决方案也会变得更加混乱,因为你增加了 no。主题。


另一种方法

或者,最好的方法是将多个流映射到一个主题,其中每个流由一个键分隔(就像您使用 IP:Port 组合一样),然后让多个消费者每个订阅一组特定的分区作为由键决定。分区是 Kafka 的可扩展性点。

缺点:虽然您可以增加编号。分区,您不能减少它们。


数据类型很重要

如果您的信息流是异构的,也就是说,它们不太可能共享一个共同的主题,您可以创建更多主题。

通常,主题由它们托管的数据和/或它们的消费者对主题中的数据执行的操作决定。如果您的所有消费者都做同样的事情,即具有相同的处理逻辑,那么选择一个具有多个分区的主题是合理的。

需要考虑的几点:

与您当前的解决方案不同(我想),一旦收到消息,它在接收和处理后不会丢失,而是继续留在主题中,直到配置的保留期。

在确定密钥策略时要小心谨慎,即哪些消息进入哪些分区。如前所述,如果您的所有消费者都做同样的事情,那么他们都可以在一个消费者组中分担工作量。

属于同一组的消费者执行一项共同任务,并将订阅由分区分配者确定的一组分区。然后,每个消费者将获得一组密钥,即一组流或根据您当前的解决方案,一组一个或多个 IP:Port 对。