何时使用参与者而不是消息解决方案(如WebSphere MQ或Tibco Rendezvous)?


82

我已阅读What design decisions would favour Scala's Actors instead of JMS?的问题和答案。

通常,我们使用已存在多年的消息传递解决方案:使用WebSphere MQ或Apache ActiveMQ等JMS实现进行点对点通信,或使用Tibco Rendevous进行多播消息传递。

它们非常稳定,经过验证并提供高可用性和高性能。尽管如此,配置和设置似乎比Akka复杂得多。

时候和为什么我应该用阿卡,对于其中上述产品的一些使用情况 - 的WebSphere MQ或ActiveMQ的 - 已经成功地沿用至今?为什么我应该考虑在未来的项目中使用Akka而不是WebSphere MQ或Tibco RV?

什么时候应该避免Akka?它是否提供与其他解决方案相同的高可用性和性能?或者将Akka与其他消息传递中间件进行比较是否是一个糟糕的主意?

也许有也是在JVM环境中的另一消息解决方案,这是我应该除了JMS(点至点),TibcoRV(多播)和阿卡考虑?

+2

http://stackoverflow.com的一个例子/ questions/4648280/scala-actors-vs-jms/4648843#4648843可能会有用。 18 4月. 112011-04-18 01:46:16

4

我不是在消息系统的专家,但您可以用阿卡在您的应用程序将它们合并,获得两全其美。下面是你可能会发现与阿卡和消息系统ZeroMQ试验,在这种情况下有用的例子:

https://github.com/zcox/akka-zeromq-java

+5

ZeroMQ不完全是一个消息系统。这是一些改进的套接字。全面的消息系统比ZeroMQ复杂得多。在你的链接上的项目似乎只是ZeroMQ与Akka的一个简单包装。 22 10月. 122012-10-22 20:45:54


67

第一关“老”的消息系统(MQ)是老年人中实现,但他们是一个较新的在工程思想上:事务持久队列。 Scala Actors和Akka可能是一个较新的实现,但是构建在Actors的一个较老的并发模型上。然而

两个车型最终成为在实践中非常相似,因为它们都是基于事件的消息:请参阅我的回答RabbitMQ vs Akka

如果你打算只为JVM代码,然后阿卡可能是一个不错的选择。否则,我会使用RabbitMQ。

另外,如果你是一个Scala开发人员,那么Akka应该是一个不容小觑的人。然而,Akka的Java绑定不是非常Java的,因为Scala的类型系统,需要投射。

而且在Java中的人通常不会让我给你推荐消息不一定不可变对象。因此,Java中非常容易使用Akka意外地执行某些操作,这些操作不会扩展(使用可变对象的消息,依靠奇怪的关闭回调状态)。使用MQ,这不是一个问题,因为消息总是以代价的速度进行序列化。通过Akka他们通常不会。

与大多数MQ相比,Akka在大量消费者中的规模也更好。这是因为对于大多数MQ(JMS,AMQP)客户端,每个队列连接都需要一个线程...因此大量的队列==大量永久运行的线程。但这主要是客户端问题。我认为ActiveMQ Apollo拥有一个非阻塞调度器,据称可以解决AMQP的这个问题。 RabbitMQ客户端具有允许您组合多个消费者的渠道,但仍然存在大量消费者可能导致死锁或连接死亡的问题,因此通常会添加更多线程来避免此问题。

这就是说Akka's remoting是相当新的,可能仍然不提供传统消息队列提供的所有可靠的消息保证和QoS(但每天都在改变)。它也通常是点对点的,但是我认为是否支持服务器 - 点对点,这通常是大多数MQ系统所做的(即单点故障),但是存在点对点的MQ系统(RabbitMQ是服务器端的,对等)。

最后RabbitMQ和Akka实际上是一个很好的配对。您可以使用Akka作为RabbitMQ的包装,因为RabbitMQ不能帮助您处理消息消耗和本地路由消息(在单个JVM中)。

当选择阿卡

  • 有大量的消费者(认为百万)。
  • 需要低延迟
  • 打开的演员并发模型

实例系统:交互式实时聊天系统

当选择MQ

  • 需要与许多不同的系统集成(即非JVM)
  • 消息可靠性比延迟更重要
  • 想了解更多的工具和管理界面
  • 因为以前分在长时间运行的任务,更好地
  • 想使用比演员不同的并发模型

示例系统:预定的交易批处理系统

基于有关意见编辑

我假设OP是关心分布式处理,其中Akka和消息队列都可以处理。那是我以为他在谈论distributed Akka使用Akka进行本地并发是一个苹果橙色比较大多数消息队列。我说最多的是因为你可以在本地应用消息队列模型作为并发模型(即主题,队列,交换),Reactor库和simple-react都是这样做的。

选择正确的并发模型/库对于低延迟应用程序非常重要。分布式处理解决方案(如消息队列)通常并不理想,因为路由几乎总是通过线路完成,而线路明显比应用内部的要慢,因此Akka将是一个更好的选择。不过,我相信一些专有的MQ技术允许本地路由。也正如我前面提到的,大多数MQ客户端都非常愚蠢的关于线程化,并且不依赖于非阻塞IO并且每个连接/队列/通道都有一个线程......具有讽刺意味的是,非阻塞io并不总是低延迟,而是通常更多的资源高效。

正如你所看到的,分布式编程和并发编程的主题是相当大的,每天都在变化,所以我的初衷并不是混淆,而是集中在分布式消息处理的一个特定领域,这是我通过OP关心的。在并发性方面,人们可能希望将他们的搜索集中在“反应性”编程(RFP /流)上,这是一种“更新”但类似的模型与行动者模型和消息队列模型,所有这些模型通常可以组合,因为它们是基于事件的。

+3

我认为对一个错误问题的回答是不对的。您无法比较消息队列和并发模型。它们的构建是为了解决完全不同的任务,并且只有“消息”这个词有共同之处。 05 3月. 152015-03-05 22:22:05

+1

嗯,是的,没有。 Akka支持分布式消息传递,您可以非常轻松地构建消息队列范例(谷歌Spring的反应堆)的并发模型。真的,现在唯一的区别是RabbitMQ有持久的消息..哦,等待Akka现在也支持。他可能会在标题中说“演员”,但明确指出了与许多基于消息的系统(并发和分布式)具有大量重叠的Akka。 06 3月. 152015-03-06 01:16:35

+3

BTW @IgorS。与消息队列一起使用的典型并发模型称为SEDA(staged event driven architecture)。除了使用队列,主题和交换本身,它本身就是一个并发模型(它恰好也是分布式模型,就像演员模型一样)。当有人说“错误的问题”时,我也非常鄙视。除了不恰当的问题,什么时候问题可能会出错?它的狡猾和精英主义者可以这样说。 06 3月. 152015-03-06 01:38:23

  0

问题不对,作者不应该问这个问题。情况正好相反 - 它应该被问到,但它涉及比较消息代理实施和演员模型框架。 如果询问有关EDA的问题,我甚至不会提及并发性作为此方法的优势,而是可伸缩性,问题分解,松散耦合,长期可维护性,SLA遵从性 - 除并发之外的所有内容。 但是,如果我被问及如何实现可以处理数百万并发请求的高度并发系统,那么演员模型就会起作用。 06 3月. 152015-03-06 03:19:16

  0

所以我知道你可以从akka和rabbitMQ的初衷中抽象出来,并且说“他们都支持消息传递”并且因此具有可比性,但是我想要考虑一个问题,即akka和rabbitmq可以互换,找到一个。 06 3月. 152015-03-06 03:23:55

  0

我从来没有说过它们是可以互换的。我甚至说他们在一起工作很好,为什么。但他显然是在讲这里发放的阿卡,而不是阿克卡的演员库。我就是这么读的。随意编辑我的帖子,因为你的观点是有效的,可能会混淆在帖子上绊倒的其他人。 06 3月. 152015-03-06 11:33:53

  0

@IgorS。我试着修复答案,但这很难,因为添加并发使得答案太广泛,但我希望它可以帮助其他人。 06 3月. 152015-03-06 12:47:29

  0

Akka Java API - 现在非常干净,尤其是JDK 8 lambda。我怀疑,如果他们在JDK 10中引入价值对象,它会变得更好。 18 10月. 172017-10-18 13:57:50


0

Akka-Camel将是一个比ZeroMQ更好的例子 - ZeroMQ是一个直接tcp到tcp通信(因此为零 - 没有消息队列)。

使用AkkaCamel,您可以抽象出队列并直接从演员处产生/消耗消息,而不需要任何代码来处理消息队列消息推/拉。

您可以放弃akka-zeromq并直接使用Akka进行远程处理。 我觉得阿卡-zeromq正在从核心库中删除,但我们建立了一个良好的zeromq库阿卡称为斯卡拉 - zeromq(https://github.com/mDialog/scala-zeromq

阿卡有几个关键的核心使用情况:

1)可变状态

通过将其隐藏到actor中来处理共享状态更容易。作为演员处理消息同步,你可以在一个演员保持状态,并通过演员API

2)分布暴露具有高一致性的那场

并发是在阿卡免费的,所以你说这的的确确是解决分配问题。跨机器和核心分布。 Akka已经建立了“位置透明度”来通过电报发送消息。它还具有集群和模式,可以扩展单个服务。这使得用于分发的很好的解决方案(例如微服务架构)

下面是使用阿卡和ActiveMQ与阿卡-骆驼(使用Java8)

import akka.actor.Props; 
import akka.camel.Camel; 
import akka.camel.CamelExtension; 
import akka.testkit.TestActorRef; 
import akka.testkit.TestProbe; 
import org.junit.Ignore; 
import org.junit.Test; 
import akka.camel.javaapi.UntypedProducerActor; 
import akka.camel.javaapi.UntypedConsumerActor; 
import static com.rogers.totes.TotesTestFixtures.*; 
import org.apache.activemq.camel.component.*; 

public class MessagingTest { 
    @Test @Ignore 
    public void itShouldStoreAMessage() throws Exception{ 
     String amqUrl = "nio://localhost:61616"; 
     Camel camel = (Camel) CamelExtension.apply(system); 
     camel.context().addComponent("activemq", ActiveMQComponent.activeMQComponent(amqUrl)); 

     TestProbe probe = TestProbe.apply(system); 
     TestActorRef producer = TestActorRef.create(system, Props.create((Producer.class))); 
     TestActorRef consumer = TestActorRef.create(system, Props.create((Consumer.class))); 
     producer.tell("Produce", probe.ref()); 

     Thread.sleep(1000); 
    } 
} 

class Producer extends UntypedProducerActor{ 

    @Override 
    public String getEndpointUri() { 
     return "activemq:foo.bar"; 
    } 
} 

class Consumer extends UntypedConsumerActor{ 

    @Override 
    public String getEndpointUri() { 
     return "activemq:foo.bar"; 
    } 

    @Override 
    public void onReceive(Object message) throws Exception { 
     System.out.println("GOT A MESSAGE!" + message); 

    } 
}