我为什么要使用JMS而不是RMI + Queue?

时间:2010-08-09 16:53:20

标签: java queue jms rmi

目前我正在使用RMI或hessian library在我的服务器和客户端之间进行通信(通过LinkedBlockingQueue)。现在我读到了JMS也可以在这个领域使用的内容。它是否正确?如果是的话,你是否愿意给我一个简单的优缺点列表,因为它似乎是一个非常复杂和“全面的企业”领域。

有什么好处?与RMI + Queue相比,性能如何呢? JMS可以击败RMI +队列吗?

PS:我知道有similar questions,但我希望将JMS与RMI +队列进行比较。

5 个答案:

答案 0 :(得分:14)

简化比较(不是特别针对JMS,更像是与MQ的比较)......

  1. 自动重试
    如果您是客户端对服务器执行RMI并且由于某种原因RMI失败,则必须自己重试。如果您使用JMS并且您是客户端,则只需发送JMS消息。当无法访问服务器时,将存储您的消息,然后在服务器再次启动时传送。

  2. 持久队列
    由于您使用的是LinkedBlockingQueue,因此您可以在内存中拥有有界队列或无界队列。一旦队列已满,前者将开始捕获线程,并最终在高负载下失败。后者最终会抛出OutOfMemoryError。如果你使用JMS,它可以自动开始“持久化”消息到“持久存储”。通常,“持久存储”是DB,它通常比内存中队列容量大得多。当然,当服务器发生故障时,内存中队列的内容会丢失,而在JMS中,您可以选择在此类事件中幸存的持久消息/持久消息。这也允许您进行群集,这对企业程序也非常重要......

  3. 抽象
    您将使用标准化的API(好吧,您在RMI中也有协议,但如果您想要传递消息,则MQ提供比RMI +内存中队列更多的高级抽象)。这意味着,您可以使用JMS的未来实现。也许某些东西不需要DB来提供持久性和持久性,比今天的实现更具可扩展性。或者也许您可以将相同的消息发送到完全不同的服务,因为standerization。基本上,较高的抽象可以为您提供灵活性,RMI +内存中的队列不会。

  4. 前段时间,我曾与一家大公司合作,希望使用他们的内部框架来整合我们的东西。那时我们没有使用MQ。我们要求他们使用我们自己的基于RMI的异步协议。相信我,我们非常非常后悔这个决定......

答案 1 :(得分:8)

其他答案涵盖了JMS的许多方面,但我觉得非常重要的一个需要更多重点,即JMS以交易方式支持多个并发消费者。这对我来说是杀手级功能

  1. 您可以使用非交易的单个消费者和生产者轻松构建系统。
  2. 您还可以(或多或少)事务性进行更多工作。
  3. 同样,您可以相对轻松地添加对多个生产者和单个消费者的支持,例如,如果您使用事务数据库来存储消息。
  4. 但是多个并发消费者变得非常困难并且消息消费是事务性的。这基本上需要一个非平凡的锁定方案,即使使用事务数据库,任务也不容易。
  5. 当我们谈到JMS 可扩展性时,我们会谈到这个:应用程序的能力。服务器添加/删除使用者/生产者来管理负载。

    JMS的其他优点是服务质量和管理,例如重新传递尝试,死信息队列,监控等

    如果你真的不需要它,一个稍微简单的解决方案可能会起作用。您还可以看到我的另一个答案,其中我提到了类似的问题:Why choosing JMS for asynchronous solution ?

答案 2 :(得分:2)

您在解决方案的“队列”部分使用了什么?你自己的代码?

JMS只是某个供应商排队系统之上的API,但它包含了远程处理方面。因此,从客户端的角度来看,您只需将消息放入队列(如果您正在使用pub sub,则为主题),并忘记它。基础设施将其传递给听众。

我认为JMS的许多功能来自排队基础设施的实施质量,而不是API本身,这非常简单。

简单的RMI不能很好地扩展或处理可靠性问题,良好的排队系统既可以扩展又可以恢复。

我认为公平地说,JMS和Java EE的其余部分旨在使您的应用程序具有企业级质量。最初我认为Java EE总体上很复杂,但我认为JMS是最简单的角落之一。今天,我不确定编写RMI +你自己的排队是否比使用JMS更容易。

可能一个显着的区别是,使用JMS几乎假设你有一些基础设施,如App Server。

答案 3 :(得分:1)

JMS是事务性的,可以与数据库事务协调 JMS将生产者和消费者分离,这意味着他们不需要同时运行 JMS保证交付,这意味着如果发生故障,保证消息可以到达(取决于故障类型可能需要群集)。
JMS可以执行同步,异步点对点以及发布/订阅 大多数JMS实现使用可以与其他语言操作系统一起使用的排队系统。

答案 4 :(得分:0)

'自动重试 如果您是客户端对服务器执行RMI并且由于某种原因RMI失败,则必须自己重试。如果您使用JMS并且您是客户端,则只需发送JMS消息。当无法访问服务器时,将存储您的消息,然后在服务器再次启动时传送。 “

我认为答案具有误导性。它在发送到目的地的意义上具有弹性,在没有消费者的情况下,消息将被存储,直到该消息的消费者或该消息过期为止。这假定JMS代理是可行的。

如果您尝试向无法访问的代理发送消息,那么您应该获得JMSException,并且在这种意义上,您的客户端消息可能会丢失,除非您的应用程序提出一些附加条件来存储它们并重试。从这个意义上讲,JMS服务器的客户端与RMI服务器的客户端行为相同。如果该服务器关闭,您仍将丢失该消息。