我一直在研究各种通信技术/体系结构/模式/实现(阅读:流行语),包括Web服务(WCF,Axis2),ESB,SOA,并希望了解有关消息传递的JMS。
从概念上讲,JMS听起来很简单。我的看法是它是一个中间代理,管理来自发布者的消息并将它们路由到适当的订阅者。这是通过在发布消息时对消息进行排队,并在接收消息时将消息出列来完成的。
问题1:我对JMS的基本理解是否正确?
在阅读有关技术时,让我感到困惑的一件事就是在某个特征上进行了某种程度的(有意或无意的)挥手动作。
根据我的基本理解,必须运行JMS提供程序才能发送或接收消息。我对发布的假设是JMS提供程序只是等待消息发布,然后将其存储在队列中(内存或数据库支持,具体取决于实现)。但是,我不太确定接收是如何工作的。
问题2:如果没有消息可以接收(通常)阻止?
问题2b:如果是这样,阻塞是如何实现的?客户端是否不断轮询消息?在发布消息之前,服务器是否只是不响应(如何在没有超时的情况下工作?)提供商是否会向收件人发起呼叫?
问题2c:如果没有,如何在不影响绩效的情况下及时确保收到消息?
基本描述似乎倾向于单个JMS提供程序,以确保集中管理消息而不会丢失。我可以看到缩放是一个问题。
问题3:JMS如何扩展?
在扩展时,我可以看到存在复杂性以确保将单个消息传递给所有适当的订阅者,而不管哪个物理服务器接收到该消息。
问题3b:JMS实施如何确保在规模化环境中可靠交付?
请注意,尽管这些问题与JMS有关,但它们可能适用于任何邮件基础结构。我欢迎特定于JMS的答案以及那些更通用或甚至特定于其他技术的答案。
答案 0 :(得分:19)
我试图根据我在JMS上的经验回答几个问题。
答案1: - JMS是Java Message Service API;它为Java客户端提供了访问消息传递框架的统一接口。 JMS API下面是符合JMS的消息传递提供程序,例如WebSphere MQ提供程序。 JMS支持通过任何消息传递协议将有效负载传输到目标,即。队列和主题。 这些是JMS的基础知识。
如何接收工作?
JMS规范提供了两个重要的类: - MessageConsumer
和MessageListener
。 MessageConsumer
类允许JMS客户端通过调用任何receive()
方法来同步接收JMS消息。在收到消息之前,此调用将阻塞线程。
否则,可以通过将MessageListener
的对象注册到MessageConsumer
来进行异步接收。
JMSProvider知道消息是在其本地目的地到达的,它的工作是将消息传递给轮询消息使用者线程或非轮询注册消息监听器线程。
回答2: -
MessageConsumer
API有两种接收变体:receive()
和receive(long timeout)
。后一种变体允许MessageConsumer
线程阻塞,直到消息在特定超时时间内到达,否则超时。
不同的消息传递框架可能以不同的方式实现阻止功能。由于JMS对象是JNDI受管对象,并且提供程序特定的代理对象被返回到JMS客户端,这意味着客户端不知道在后台发生阻塞的方式。特定消息传递框架可以在特定时间段之后选择消息消费者线程轮询。或者,它可以选择阻止直到发送通知。
我不确定您是否正在寻找符合特定JMS的消息传递框架的答案?
答案3: - 我想通过JMS扩展你的意思是拥有许多发布者/订阅者,多个物理机器上的许多目标。 JMS扩展需要支持底层消息传递提供程序以支持某种类型的群集/故障转移。因此,JMS规范不支持可伸缩性。如果我错了,请纠正我?例如,我参与了符合JMS的WebSphere MQ,它提供了集群支持。
答案 1 :(得分:5)
问题1:我对JMS的基本理解是否正确?
让我们首先获得正确的术语。你不能说JMS Provider must be running
因为provider是一个构建了JMS服务器的实体,它是必须运行的JMS服务器。因此,当我们说JMS时,我们指的是提供程序实现的一组API(技术上更为接口)。所以基本上提供者编写自己的JMS实现。例如,由Active MQ is a JMS server
Apache(provider)
我对发布的假设是JMS提供程序只是等待消息发布,然后将其存储在队列中(内存或数据库支持,具体取决于实现)。
在某种程度上是真的。遵循不同的模型。 JMS服务器保持套接字打开。每当发送方客户端必须发送消息时,它只需打开与套接字的连接并发送消息。接收行为如何完全不同。您有拉和推送。在推送服务器中,一旦收到消息,就会将消息推送到实时接收器客户端。这也称为异步模式。在拉模型中,客户端接收器向服务器发送请求以获取消息(同步模式)。
如果没有消息可以接收(通常)阻止?
正如我之前提到的,它将取决于您使用的型号。接收器将在拉模型中被阻止(同步接收)。这也发生在会话线程中,而不是主线程。
如果是这样,阻塞是如何实现的?客户端是否不断轮询消息?
是的,客户将在拉模型的情况下不断进行投票。通常会有超时,客户端将被终止。
如果没有,如何在不影响性能的情况下及时确保收到消息?
使用异步模式。您只需注册 MessageListener ,当服务器上有消息可用时,它将在其上覆盖 onMessage(消息消息)上的消息。
问题3:JMS如何扩展?
提供商担心这是一个真正的问题。当您说所有订阅者收到消息时,您指的是 PUBSUB 通信模型(其他为 PTP )。在PUBSUB中,发送给主题的消息将被发送给订阅该主题的所有订阅者。
问题3b:JMS实施如何确保在规模化的环境中可靠交付?
可靠性?不总是。同样,这取决于用例。您可以拥有持久性以及非持久性消息。在持久消息的情况下,消息存储在DB(文件或其他)中并且确保它的传递。在非持久性消息的情况下,没有这样的保证。服务器故障可能导致邮件丢失。
答案 2 :(得分:2)
JMS支持使用同步方法消息(使用和不使用超时阻塞线程)或使用事件驱动的回调(异步消息侦听器))。
您可以决定哪种方法更适合您的需求,但您也可能需要查看实际实施情况。例如,一些JMS实现为receive()执行网络往返,因此更好地使用超时或监听器。
使用消息侦听器线程行为和消息接收暂停不像阻塞接收调用那样容易控制。通常,大多数控制都是通过使用自己的阻塞receive()调用池来实现的,这些调用具有超时,并分派给您的工作人员。
答案 3 :(得分:2)
我认为应该提到Queue和Topic之间的区别,因为消息的传递方式存在重大差异。
队列:只有一个客户端会收到一条消息。例如,为了向外扩展,您可以将10个客户端连接到同一个队列 - 但只有其中一个客户端将收到特定的消息。如果没有连接任何客户端,则消息将保留在队列中,直到有人连接或消息超时。
主题:所有客户都将收到每封邮件的副本。通常在订户场景中使用,其中许多端点可能对每个消息感兴趣。持久的用户甚至可能会停机一段时间;将保留消息,直到订户再次启动或消息超时。如果没有连接客户端并且没有持久订阅者,则将丢弃消息。
答案 4 :(得分:0)
JMS中有两种类型的消息传递域。
在PTP模型中,只有一条消息传递给一个接收方。在这里,Queue被用作 M essage O 面向 M 的中间件( MOM )。
队列负责保留消息,直到接收器准备就绪。
在PTP模型中,发送方和接收方之间没有时间依赖性。
在发布/订阅模式中,会向所有订阅者发送一条消息。这就像广播。在这里,Topic被用作面向消息的中间件,负责保存和传递消息。
在PTP模型中,发布者和订阅者之间存在时间依赖性。
M 消息 D 撕裂 B ean(MDB)