71

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

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

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

我错过了什么?- 大学教师

4

11 回答 11

70

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

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

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

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

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

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

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

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

于 2008-10-21T15:05:06.653 回答
51

在我看来,JMS 和其他基于消息的系统旨在解决需要:

  • 异步通信:应用程序需要通知另一个应用程序发生了事件,而无需等待响应。
  • 可靠性。确保一次且仅一次的消息传递。使用您的数据库方法,您必须“重新发明轮子”,特别是如果您有多个客户阅读消息。
  • 松耦合。并非所有系统都可以使用数据库进行通信。因此,JMS 非常适合用于具有可跨系统边界进行通信的解耦系统的异构环境。
于 2008-10-21T14:23:38.033 回答
7

JMS 实现是“推送”的,从某种意义上说,您不必轮询队列来发现新消息,但是您注册一个回调,该回调会在新消息到达时立即被调用。

于 2008-10-21T14:29:01.530 回答
5

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

  1. 您不需要自己编写代码(并且可能会搞砸逻辑,使其不像您想象的那么持久)。此外,第三方 impl 可能比简单的数据库方法更具可扩展性。

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

  3. 您不依赖于特定的实现,并且如果您将来的需求发生变化,可以将其换掉,而不会弄乱您的 java 代码。

于 2008-10-21T14:56:15.237 回答
5

JMS 的一个优点是支持异步处理,这也可以由数据库解决方案完成。然而,以下是 JMS 相对于数据库解决方案的其他一些好处

a) 消息的消费者可以在远程位置。公开数据库以进行远程访问是危险的。您可以通过提供额外的服务来从数据库读取消息来解决这个问题,这需要更多的努力。

b)在数据库的情况下,消息消费者必须轮询数据库中的消息,因为 JMS 在消息到达时提供回调(如 sk 所述)

c) 负载平衡 - 如果有很多消息来,很容易在 JMS 中拥有消息处理器池。

d) 一般而言,通过 JMS 实现会比数据库路由更简单且省力

于 2008-10-22T08:28:36.563 回答
2

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

JMS 的主要优点是通信实体的解耦特性 - 发送方不需要有关接收方的信息。其他优势包括集成异构平台、减少系统瓶颈、提高可扩展性以及更快速地响应变化的能力。

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

所以来到你的问题 -what is JMS good for? 我想举一个实际的例子来说明它的重要性。

日间交易

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

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

Ofcourse this is one of the factors other that reliability,security etc which makes JMS so powerful.

于 2013-09-27T07:14:15.060 回答
1

Guido 有完整的定义。根据我的经验,所有这些对于良好的合身性都很重要。

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

于 2008-10-21T14:30:25.647 回答
1

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

银行就是一个很好的例子,日内消息被用来在实时数据更改发生时传递它们。源系统很容易“翻墙”抛出消息;缺点是这些系统之间的合同方式很少,您通常会看到住院治疗是在消费者方面实施的。它的耦合几乎太松散了。

其他优势在于对许多应用程序服务器等的开箱即用的 JMS 支持以及围绕它的所有工具:持久性、监控、报告和节流。

于 2008-10-21T14:46:40.263 回答
1

这里有一些很好的例子:http: //www.winslam.com/laramee/jms/index.html

于 2010-12-03T22:10:01.510 回答
0

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

于 2008-10-21T14:32:01.430 回答
0

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

于 2010-07-25T08:14:26.210 回答