【问题标题】:Using message bus as replacement for regular message passing between actors (e.g., in scala)使用消息总线代替参与者之间的常规消息传递(例如,在 scala 中)
【发布时间】:2015-10-13 12:55:00
【问题描述】:

我有一个 Java Web 服务,我将在 Scala 中从头开始重新实现它。我有一个基于演员的新代码设计,大约有 10-20 个演员。其中一个用例的流程如下:

Actor A 获取消息 a,创建数十条 b 消息以由 Actor B 处理(可能多个实例,用于负载平衡),为 Actor C 生成多个 c 消息,等等。

在上述场景中,一条消息a 可能会导致来回发送几千条消息,但我预计每天不会超过少数a 消息(是的,这不是目前服务繁忙)。

我有以下要求:

  1. 消息不应丢失或重复。我的意思是如果系统在处理 b 消息的过程中重新启动,则应该在重新启动后拾取未处理的消息。另一方面,处理过的消息不应该再次被获取(这些消息最终会开始一些大的计算,重复它们是昂贵的)。
  2. 它应该易于扩展。我的意思是将来,我可能想在系统中添加一些其他组件,这些组件可以读取所有通信(或部分通信),例如记录发生的事情,或者计算处理了多少 b 消息,或者对 b 消息做一些新的事情(在已经发生的事情旁边)等。请注意,这些“组件”可以是用其他语言编写的独立应用程序。

我是消息总线技术的新手,但根据我的阅读,这些要求在我看来就像“消息总线”提供的东西,如 RabbitMQ、Kafka、Kestrel,但我也看到 akka 也提供了一些持久性方法. 我的问题是,考虑到各种可能性,我不知道该使用哪种技术。我读到像 Kafka 这样的东西对我的应用程序来说可能是一种过度杀伤力。但我也不确定 akka 持久性是否能满足我的两个要求(尤其是可扩展性)。

我的问题是:我应该选择企业消息总线吗?卡夫卡之类的?或者像 akka 持久性这样的东西会做吗? 或者如果我自己实现一些东西(例如,支持 AMQP 以允许可扩展性),它会更快更合适吗?

当然,如果您知道适合此目的的东西,也欢迎具体的技术建议。

【问题讨论】:

  • Akka 本身支持 at-most-once 传递(意味着消息可能会丢失)。如果你添加了 Akka Persistence,你可以通过使用 AtLeastOnceDelivery trait 实现 at-least-once 交付(意味着你可以得到重复)。但是,您想要的是exactly-once 交付。 Akka 不支持开箱即用,有人说它无法实现。参见例如dzone.com/articles/you-cannot-have-exactly-once。虽然你可以接近,但你必须为之努力。
  • 感谢@MarioCamou 的评论。事实上,我看过那个帖子。那么,我是否应该将您的建议视为“自己构建”?
  • 是的,我个人会从至少一次交付开始,然后处理重新发送和乱序消息。请注意,即使您使用 Kafka 或消息队列,您也必须考虑消息队列本身可能出现故障的事实(并且使用 Akka Persistence,您还必须考虑如果您的持久性提供程序出现故障会怎样)。

标签: scala rabbitmq amqp apache-kafka message-bus


【解决方案1】:

像 RabbitMQ 这样的消息总线(通常称为消息代理)可以“开箱即用”处理您在问题中描述的所有消息传递机制。具体来说:

RabbitMQ 具有“开箱即用”的能力:

  • 传递消息而不重复消息。
  • 扩展系统并添加日志记录并获得您所描述的统计信息。

【讨论】:

  • 感谢您的回答@joshuad2。问题是,它的开销是多少?我的意思是考虑到我的系统规模不是很大,你会推荐使用 RabbitMQ 之类的东西吗?例如,考虑维护和管理成本。
  • 与 Kafka 等其他消息代理相比,RabbitMQ 的重量非常轻。可执行文件的大小非常小,它只会使用您放入 Broker 的内容。因此,如果您在任何时候都没有很多消息在队列中,那么大小和开销都非常小,但考虑到您的路由需求,好处是很大的。
  • 好的。我接受你的回答,尽管在我真正实施和验证它之前肯定需要时间! ;-)
猜你喜欢
  • 2015-12-02
  • 1970-01-01
  • 2021-12-19
  • 2015-11-02
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
相关资源
最近更新 更多