Spring Jmstemplate.send 从 JmsListener 方法内部

问题描述 投票:0回答:1

在我们的应用程序中,我们有以下快乐路径流程:

  1. Gateway-> jmstemplate.send msg(withreplyTo=Gateway-Node-Specific_queue)到BE GenericQueue并通过监听器(Gateway-Node-Specific_queue)等待响应
  2. BE -> 通过监听器接收到消息(BE GenericQueue)
  3. 从 msg 和 jmstemplate.send msg(replyTo=BE-Node-Specific_queue)构建 Out-API 请求到 Gateway GenericQueue 并通过监听器(BE-Node-Specific_queue)等待响应
  4. 网关 -> 通过监听器(Gateway GenericQueue)接收消息,将 Http 请求转发到 out API,收到 Http 响应 jmstemplate.send 消息到 BE-Node-Specific_queue
  5. BE -> 收到来自 BE-Node-Specific_queue 的消息后,jmstemplate.send 响应消息到 Gateway-Node-Specific_queue

Node-Specific_queue 消息与 UUID-CorrelationId 相关

现在可以观察到,当在步骤 #2 和 #3 BE 尝试从

jmstTemplate.send
方法内部调用
JmsListener
到网关时,网关不会收到消息,直到控制权从 BE 侦听器方法中出来。我们不使用任何类型的交易。

我试图理解为什么它不起作用,到目前为止有效的是

jmsTemplate.send
是否在
JmsListener
方法内的单独线程中执行。为什么用线程执行这段代码
JMSListener
不起作用?是否有任何外部配置可以在不更改任何代码的情况下提供帮助?

spring-boot jms spring-jms
1个回答
0
投票

在同一线程上时,JMS 代理将不会执行 send(),直到来自侦听器的消息 receive() 得到确认。这就是为什么在侦听器方法存在之前您看不到消息的原因。此上下文是线程本地的,因此如果您启动一个新线程,您将不会看到此行为。

我怀疑您使用相同的 JMS 连接工厂进行接收和侦听。如果您对这些操作使用不同的 JMS 连接工厂,您可能看不到此行为。

根据你的问题...

这是一个很长的问答。 AbstractMessageListenerContainer 的 javadoc 可能会有所帮助。

最初,当用户使用 DefaultMessageListenerContainer 时,默认行为是立即 ACK 传入消息。用户必须知道,如果发生异常,传入消息已被确认,并且可能会发生消息丢失。您必须设置某种形式的事务,以便延迟发送传入消息的 ACK,直到处理完成。

为此目的使用 JmsTransactionManager 很常见。请注意,

JmsTransactionManager
只能管理单个 JMS 连接工厂。这就是为什么使用不同的连接工厂可以解决与
JmsTransactionManager
的事务。

使用现代模板,这是为您设置的。您实际上正在使用事务,并且当侦听器存在时,入站消息将被确认(除非您使用其他事务方法扩展事务上下文)。

© www.soinside.com 2019 - 2024. All rights reserved.