【发布时间】:2015-10-13 12:55:00
【问题描述】:
我有一个 Java Web 服务,我将在 Scala 中从头开始重新实现它。我有一个基于演员的新代码设计,大约有 10-20 个演员。其中一个用例的流程如下:
Actor
A获取消息a,创建数十条b消息以由 ActorB处理(可能多个实例,用于负载平衡),为 ActorC生成多个c消息,等等。
在上述场景中,一条消息a 可能会导致来回发送几千条消息,但我预计每天不会超过少数a 消息(是的,这不是目前服务繁忙)。
我有以下要求:
- 消息不应丢失或重复。我的意思是如果系统在处理 b 消息的过程中重新启动,则应该在重新启动后拾取未处理的消息。另一方面,处理过的消息不应该再次被获取(这些消息最终会开始一些大的计算,重复它们是昂贵的)。
- 它应该易于扩展。我的意思是将来,我可能想在系统中添加一些其他组件,这些组件可以读取所有通信(或部分通信),例如记录发生的事情,或者计算处理了多少 b 消息,或者对 b 消息做一些新的事情(在已经发生的事情旁边)等。请注意,这些“组件”可以是用其他语言编写的独立应用程序。
我是消息总线技术的新手,但根据我的阅读,这些要求在我看来就像“消息总线”提供的东西,如 RabbitMQ、Kafka、Kestrel,但我也看到 akka 也提供了一些持久性方法. 我的问题是,考虑到各种可能性,我不知道该使用哪种技术。我读到像 Kafka 这样的东西对我的应用程序来说可能是一种过度杀伤力。但我也不确定 akka 持久性是否能满足我的两个要求(尤其是可扩展性)。
我的问题是:我应该选择企业消息总线吗?卡夫卡之类的?或者像 akka 持久性这样的东西会做吗? 或者如果我自己实现一些东西(例如,支持 AMQP 以允许可扩展性),它会更快更合适吗?
当然,如果您知道适合此目的的东西,也欢迎具体的技术建议。
【问题讨论】:
-
Akka 本身支持 at-most-once 传递(意味着消息可能会丢失)。如果你添加了 Akka Persistence,你可以通过使用
AtLeastOnceDeliverytrait 实现 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