【问题标题】:How to understand the "synchronous" and "asynchronouns" messaging in JMS?如何理解 JMS 中的“同步”和“异步”消息传递?
【发布时间】:2014-04-01 02:01:00
【问题描述】:
看了一些JMS的文档后,我完全被synchronous和asynchronouns这句话弄糊涂了。
查看此页面:http://docs.oracle.com/cd/E19798-01/821-1841/bncdq/index.html
同步
您使用接收方法同步消费消息。
调用 start 方法后,您可以随时使用此方法:
connection.start();
Message m = consumer.receive();
connection.start();
Message m = consumer.receive(1000); // time out after a second
要异步使用消息,请使用消息侦听器,将在下一节中介绍。
异步
JMS 消息监听器
消息侦听器是充当消息的异步事件处理程序的对象。此对象实现 MessageListener 接口,其中包含一个方法 onMessage。在 onMessage 方法中,您定义了消息到达时要执行的操作。
您可以使用 setMessageListener 方法向特定的 MessageConsumer 注册消息侦听器。例如,如果你定义了一个名为Listener的类,它实现了MessageListener接口,你可以如下注册消息监听器:
Listener myListener = new Listener();
consumer.setMessageListener(myListener);
我有两个问题:
据我了解,JMS 的本质是异步的。生产者向队列/主题发布消息,不需要等待消费者。这是异步行为。怎么可能“同步”?
如果“mesageListener”是异步的,但在我使用 spring-jms 的测试中,我发现它总是在线程中运行。这意味着,如果我在 onMessage 中写入 Thread.sleep(2000),则必须等待 2 秒才能处理下一条消息。是“异步”的吗?
【问题讨论】:
标签:
java
asynchronous
jms
synchronous
【解决方案1】:
我对同步/异步的理解不同。
同步:调用者(发送者)必须等到收到消费者的响应(直到超时)——请求/回复模式
异步:调用者(发送者)只是发布消息并继续其工作,而消费者在消息到达时立即处理——单向请求
任何MOM(Message Oriented Middle ware) 都遵循促进异步通信的服务激活器模式。我的一个项目围绕 JMS 实现了一个框架,以使通信真正同步。
- 任何消息都有 2 个部分。
一种。元数据属性
湾。有效载荷
- 将属性“reply-to-queue”设置为随机生成的值
- 确保 MOM 框架创建名称来自 #2 的临时队列
- 确保发送方产生线程,该线程侦听在 #3 中创建的临时队列
- 发布消息并阻止发送方,直到它收到消息到临时队列
- 确保消费者截获“reply-to-queue”标头并发布响应
这是使基于 MOM 的通信表现得像同步一样的方法之一。您可能会发现其他实现,例如 request-reply mechanism。
【解决方案2】:
您正在端到端地查看它:从发布者到消费者。是的,无论同步/异步消费者如何,它都是从发布者到消费者的异步交付。但是,您问题中的同步/异步仅适用于消费者,即从 JMS 代理(例如:ApacheMQ)到消费者。正如其他人指出的那样,同步消费者按顺序从代理中提取消息并等待消息。异步消费者注册一个回调,将消息推送给他们(onMessage)。异步消费者可以在这些消息从 JMS 代理异步传递给他们的同时做其他事情。
【解决方案3】:
就像我理解的那样:
异步 - MessageListener: 在侦听队列的服务器上使用它。当消息到达时,立即处理。服务器一直在监听这个队列。
同步 - consumer.receive(1000): 在客户端应用程序上使用它,该应用程序不时需要检查消息是否针对此客户端。示例:每 60 秒轮询一次。这只会很快打开与服务器的连接。 1000 毫秒将保持此连接打开。如果消息在这 1000 毫秒内到达,则消息被消费并关闭连接。
【解决方案4】:
如果您像这样更好地理解它,consumer.receive() 使用 pull 模型:您从队列中读取并被阻塞等待该消息直到它到来,或者某个超时已经过去。
使用侦听器使用 push 模型:您注册一个侦听器,当有消息进来时,在单独的线程中调用该侦听器。
Java 中的一切都是在一个线程中完成的,监听器调用也不例外。侦听器消息处理是否阻止处理队列中的其他消息取决于有多少线程专用于消息处理。如果您将 Spring 配置为使用 5 个线程的池来异步处理消息,那么 5 个侦听器将能够并行处理消息。