JMS有什么用?[关闭]


71

我正在寻找JMS是一个好的解决方案的问题的(简单)示例,以及在这些情况下JMS是一个好的解决方案的原因。过去,当消息不一定立即由B处理时,我只是将数据库用作将消息从A传递到B的一种方式。

这种系统的一个假设示例是,应在注册后的24小时内向所有新注册的用户发送一封欢迎电子邮件。出于争论的考虑,假设数据库不记录每个用户注册时的时间,而是将每个新用户的引用(外键)存储在pending_email表中。电子邮件发件人作业每24小时运行一次,向该表中的所有用户发送一封电子邮件,然后删除所有未决的记录。

这似乎是应该使用JMS的问题,但是我不清楚JMS相对于我所描述的方法会有什么好处。DB方法的一个优点是消息是持久的。我知道JMS消息队列也可以保留,但是在那种情况下,JMS与我描述的“数据库作为消息队列”方法之间似乎没有什么区别?

我想念什么?-唐


1
本质上,您pending_email当前正在将该表用作消息队列。
马特b

Answers:


69

JMS和消息传递实际上是两件完全不同的事情。

  • 发布和订阅(向感兴趣的尽可能多的消费者发送消息-有点像向电子邮件列表发送电子邮件,发件人无需知道订阅了谁
  • 高性能可靠的负载平衡(消息队列)

查看有关队列与主题比较的更多信息

您正在谈论的情况是第二种情况,是的,您可以使用数据库表来模拟消息队列。

主要区别在于JMS消息队列是为高吞吐量而设计的高性能,高并发负载均衡器。您通常每秒可以向许多进程和线程中的多个并发使用者发送每秒数万条消息。原因是消息队列基本上是高度异步的-好的JMS提供程序会提前将消息流传输给每个使用者,以便一旦有使用者可用,就可以在RAM中处理成千上万条消息。这导致大量的吞吐量和非常低的延迟。

例如,想象使用数据库表编写Web负载均衡器:)

使用数据库表时,通常一个线程倾向于锁定整个表,因此在尝试实现高性能负载均衡器时,您倾向于获得非常低的吞吐量。

但是像大多数中间件一样,这一切都取决于您的需求。如果您的系统吞吐量低,每秒只有几条消息,请随时使用数据库表作为队列。但是,如果您需要低延迟和高吞吐量-那么强烈建议使用JMS队列。


4
>使用数据库表时,通常>一个线程趋向于锁定整个表>因此您趋向于获得非常低的吞吐量,我想一个可以启用行级锁定。
Seun Osewa

4
即使行级锁定也无济于事。您如何在SQL中获得许多竞争的JDBC连接来执行一个查询,即“在不锁定其他任何客户端的情况下获取队列中的下一条消息”的查询即使使用行级锁定,每个客户端也只会阻塞同一行:)
詹姆斯·斯特拉坎

3
不,您实际上可以通过锁定行并抓住下一行。数据库过大的原因是它存储在硬件上,因此在电源故障的情况下,您的消息将得到保证。对于简单的管道操作来说,这是过大的选择。
Ender Wiggin'2

50

我认为JMS和其他基于消息的系统旨在解决需要解决的问题:

  • 异步通信:一个应用程序需要通知另一个事件已经发生,而无需等待响应。
  • 可靠性。确保一次性发送消息。使用数据库方法时,您必须“重新发明轮子”,特别是如果有多个客户端在阅读消息的话。
  • 耦合松动。并非所有系统都可以使用数据库进行通信。因此,JMS非常适合在具有可以在系统边界上进行通信的解耦系统的异构环境中使用。

1
八年后,我读了“一次又一次的消息传递”,我笑了。
Guido

你为什么笑?
Surasin Tancharoen

1
我认为一次性发送消息与物理定律不兼容。我们应该能够以光速发送消息。
Guido

@GuidoGarcía在发生异步调用的情况下,一旦消费者结束为事件提供服务,生产者将如何得到通知?我通常会继续将消费者添加到队列中的新结果,还有其他方法吗?
Junchen Liu

7

JMS实现是“推送”的,在某种意义上,您不必轮询队列即可发现新消息,而是注册了一个回调,一旦有新消息到达,该回调便被调用。


5

解决原始评论。最初描述的是(点对点)JMS的要旨。但是,JMS的好处是:

  1. 您不需要自己编写代码(也可以弄乱逻辑,以便它不像您认为的那样持久)。同样,第三方隐式实现可能比简单的数据库方法更具可伸缩性。

  2. jms处理发布/订阅,这比您给出的点对点示例要复杂一些

  3. 您不受特定实现的束缚,并且可以在将来需要更改时将其替换出来,而无需使用Java代码。


5

JMS的优点之一是支持异步处理,这也可以通过数据库解决方案来完成。但是,以下是JMS相对于数据库解决方案的其他一些好处

a)消息的使用者可以在远程位置。公开数据库以进行远程访问很危险。您可以通过提供其他服务来从数据库读取消息来解决此问题,这需要更多的工作。

b)对于数据库,消息使用者必须轮询数据库以查找消息,其中,当消息到达时,JMS提供回调(如sk所述)

c)负载平衡-如果有大量消息传入,则JMS中很容易拥有消息处理器池。

d)与数据库路由相比,通过JMS的一般实现将更简单且花费更少的精力


d)不同意-如果您是jms的新手,并且团队中的每个人都知道如何处理db,则情况将完全相反
Kalpesh Soni 2015年

对D:这非常取决于您已经拥有。在拥有消息传递基础结构的情况下,重用它很简单。但是,如果JMS确实“简单”,我不会三思而后行。
16th

2

JMS是用于在两个或多个客户端之间传输消息的API。它的规范是在JSR 914下定义的。

JMS的主要优点是通信实体的分离性质-发件人不必具有有关接收者的信息。其他优势包括集成异构平台,减少系统瓶颈,增加可伸缩性以及对变更做出更快响应的能力。

JMS只是一种接口/ API,必须实现具体的类。这些已经由各种组织/提供商实施。他们被称为JMS提供者。示例是IBM的WebSphere或Fiorano Software的FioranoMQ或Apache,HornetQ,OpenMQ等的ActiveMQ。其他使用的术语是管理对象(主题,队列,连接工厂),JMS生产者/发布者,JMS客户端和消息本身。

因此,提出您的问题-what is JMS good for? 我想举一个实际的例子来说明它的重要性。

日内交易

有一个称为LVC(最后值缓存)的功能

在交易中,股价由发布者定期发布。每个共享都有一个与其关联的主题。现在,如果您知道主题是什么,那么您必须知道消息不会像队列那样保存。消息在消息发布时被实时发布给订阅者(耐久订阅者例外,它们从创建之时起就发布了所有消息,但是我们又不想获得过高的股票价格而放弃了这种可能性使用它)。因此,如果客户想知道股票价格,他可以创建一个订阅者,然后他必须等到下一个股票价格发布(这又不是我们想要的价格)。这就是LVC发挥作用的地方。每个LVC消息都有一个关联的密钥。如果一条消息是用LVC密钥(针对特定股票)发送的,然后是另一条具有相同密钥的更新消息,则更新消息将覆盖前一个消息。每当订阅者订阅一个主题(已启用LVC)时,订阅者将获得具有不同LVC密钥的所有消息。如果我们为每个上市公司保留唯一的密钥,那么当客户订阅该密钥时,它将获得最新的股价,并最终获得所有更新。

当然,这是使JMS如此强大的可靠性,安全性等其他因素之一。


1

Guido具有完整的定义。根据我的经验,所有这些对于保持健康都很重要。

我见过的用途之一是在仓库中进行订单分配。想象一下一家办公用品公司,其中有大量的仓库为大型办公室提供办公用品。这些订单将被送到一个中央位置,然后被分批以分配给正确的仓库。在大多数情况下,仓库没有高速连接或需要高速连接,因此通过拨号调制解调器将订单下推到那里,这就是异步输入的地方。电话线也不是那么重要,因此一半的订单可能会收到,这是可靠性很重要的地方。


1

关键优势是将不相关的系统解耦,而不是让它们共享公用数据库或构建自定义服务来传递数据。

银行就是一个很好的例子,当日消息传递可用来实时传递实时数据变化。源系统很容易在墙上“抛出”消息。不利的一面是这些系统之间的合同方式很少,您通常会看到在消费者方面实施住院治疗。耦合太松散了。

其他优势还包括对许多应用程序服务器等的开箱即用的JMS支持,以及围绕它的所有工具:持久性,监视,报告和限制。



0

“数据库作为消息队列”解决方案可能会很繁重。JMS解决方案之间的联系不太紧密,因为消息发件人不需要了解有关收件人的任何信息。这也可以通过在“数据库作为消息队列”中添加一些额外的抽象来完成,因此这并不是一个巨大的胜利...此外,您还可以通过“发布和订阅”方式使用队列,这取决于使用什么方便您正在努力实现。这也是进一步分离组件的好方法。如果您所有的通信都在一个系统内和/或具有可立即用于应用程序的日志非常重要,则您的方法似乎不错。如果在单独的系统之间进行通信,那么JMS是一个不错的选择。


0

JMS与JTA(Java事务API)和JPA(Java持久性API)结合使用可能非常有用。使用简单的注释,您可以将多个数据库操作+消息发送/接收放入同一事务中。因此,如果其中之一失败,则使用相同的事务机制将所有内容回滚。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.