问题
我们的处理服务是为用户界面、api和内部客户端提供服务,并监听来自kafka的命令。很少有api客户机会在短时间内创建大量的生成任务(一个任务是n条消息)。使用kafka,我们无法控制命令的分发,因为每个命令都会到达一个处理示例(aka worker)所使用的分区。因此,在处理api请求时,ui请求可能等待的时间太长。
在理想的实现中,我们应该均匀地处理所有任务,而不管其大小。处理服务的容量分布在所有活动任务中。而且,即使集群负载很重,我们也总是知道,已经到达的新任务将能够几乎立即开始处理,至少在所有其他任务的处理结束之前。
解决方案
相反,我们需要一个更像下图的体系结构,在这个体系结构中,每个客户和端点的组合都有单独的队列。这种体系结构为我们提供了更好的隔离性,以及根据每个客户动态调整吞吐量的能力。
站在制作人一边
任务来自客户机
立即为此任务创建队列
将所有消息发送到此队列
站在消费者一边
在一个过程中,您不断更新队列列表
在其他进程中,您遵循此列表并使用例如来自每个队列的1条消息
规模消费者
问题
这种问题有什么共同的解决办法吗?使用rabbitmq或任何其他工具。н历史上,我们在项目中使用Kafka,所以如果有任何方法使用-这是惊人的,但我们可以使用任何技术的解决方案。
3条答案
按热度按时间gc0ot86w1#
我的理解是,对消息进行分区并不能确保均衡的负载平衡。我认为您应该避免创建过度工程和一些自定义的东西,这些东西将出现在kafka分区器之上,而应该考虑一个好的分区键,它将允许您高效地使用kafka。
zysjyyx42#
据我所知,您希望使用动态分配的队列从客户创建请求隔离,这将允许每个客户任务独立执行。这个问题看起来类似于网络中的线路阻塞问题
动态分配队列比较困难。这还可能导致队列数量激增,从而给基础结构带来负担。另外,有些队列可能是空的或负载很小。rabbitmq在这里没有帮助,它是一个与kafka协议不同的队列。
另一种选择是使用kafka中的自定义分区器,它可以查看分区负载并基于该负载平衡任务。如果任务本质上是独立的,并且worker中没有状态存储,那么这种方法就可以工作。
另一种选择是在客户级别进行负载平衡。在这种情况下,您可以为一组客户选择一组专用的预定义队列。具有特定ID的客户将得到一组队列的服务。这样做的缺点是,某些队列的负载可能比其他队列小。此解决方案类似于网络中的虚拟输出队列,
vbopmzt13#
为什么不使用spark来执行任务中的消息呢?我的想法是,每个worker创建一个spark上下文,然后将消息并行化。Map的函数可以基于用户使用的Kafka主题。但是,我怀疑您的队列中可能有包含消息、ui、api调用等的混合任务。这将导致更复杂的Map函数。如果您不使用独立的集群,并且正在使用yarn或类似的东西,那么您可以更改spark master使用的排队方法。