【问题标题】:How to make a JMS Synchronous request如何发出 JMS 同步请求
【发布时间】:2012-06-02 10:58:01
【问题描述】:

我有一个 web 应用程序,它预计会从只能通过消息传递 (JMS) 访问的外部应用程序获取和显示数据。

因此,如果用户在浏览器上提交请求,同一个 HTTP 请求线程必须与消息系统(MQ 系列)交互,以便同一个请求线程可以显示从消息系统接收到的数据。

我可以在这里使用一种模式吗?我在网上看到一些以这种方式使用“Correlation ID”的模糊参考:

Msg m = new TextMsg("findDataXYZ");
String cr_id = m.setCorrelationID(id);

sendQueue.send(m).

// now start listening to the Queue for a msg that bears that specific cr_id

Response r = receiverQueue.receive(cr_id);

那里有更好的东西吗?我发现的其他模式期望异步接收响应。这对我来说不是一个选项,因为我必须在同一个 HTTP 请求上发回响应。

【问题讨论】:

    标签: java architecture jms ibm-mq


    【解决方案1】:

    请求/回复消息传递模式对您的要求很有用。您通常使用 CorrelationId 来关联请求和回复消息。

    在发送请求消息时,您在消息上设置 JMSReplyTo 目的地。通常,临时队列用作 JMSReplyTo 目标。创建消费者以接收响应时,请使用带有 JMSCorrelationId 的选择器,例如

    cons = session.createConsumer(tempDestination,"JMSCorrelationId="+requestMsg.JMSMessageId);

    在另一端,正在处理请求消息的应用程序必须使用 JMSReplyTo 目标来发送响应。它还必须使用请求消息的 MessageId 并将其设置为响应消息的 CorrelationId。

    【讨论】:

    • 如果我一个接一个地发送请求,那么我应该为每个请求创建 new 临时队列吗?或者为所有请求重用相同的临时队列?甚至允许这种重复使用吗?如果是这样,哪种方法好,重用还是创建?
    • 另外,在你的建议中,如果我设置"JMSCorrelationId="+requestMsg.JMSMessageId,那么我认为我不能重用同一个消费者获得更多的响应,作为响应的相关ID会有所不同吗?此外,如果我为每个请求使用新的 tempQueue,那么我不需要设置消息选择器,因为 tempQueue 仅用于一个响应。无论哪种方式,我都没有理由设置JMSCorrelationId="+requestMsg.JMSMessageId,因为无论如何只有一个响应会到达消费者。我说的对吗?
    • 是的,如果您对每个请求都使用 tempQueue,那么您不需要使用选择器。只有在共享队列时才需要选择器。
    • 谢谢。这对我来说很有意义。现在下一个问题是,如果我在选择器中使用消息 id,那么我不能重用消费者。对吗?
    【解决方案2】:

    首先,打开响应队列。然后将该对象传递给消息上的 set reply-to 方法。这样,响应您请求的服务就知道将回复发送到哪里。通常,该服务会将消息 ID 复制到相关 ID 字段,因此当您发送消息时,获取您返回的消息 ID 并使用 that 来侦听回复队列。当然,如果您使用动态回复队列,即使这不是必需的 - 只需监听队列中的下一条消息。

    有显示所有这些的示例代码。如果您安装到默认位置,则示例代码位于 Windows 机器上的 "C:\Program Files (x86)\IBM\WebSphere MQ\tools\jms\samples\simple\SimpleRequestor.java" 或 *nix 机器上的 /var/mqm/toolsjms/samples/simple/SimpleRequestor.java

    如果您想知道“到底安装什么?” WMQ 客户端安装可免费下载为SupportPac MQC71

    【讨论】:

    • 感谢您的回答。所以看起来模式是: 1. 使用常规的“发送”队列发送请求。 2. 但是对于接收,使用“临时队列”。我安装了您提到的客户端工具,SimpleRequestor 类执行此操作:tempDestination = session.createTemporaryQueue(); consumer = session.createConsumer(tempDestination); 它看起来很棒,但它是否可以在生产环境中工作,我们期望每秒处理 1000 个此类请求?看起来我们将为每个请求创建一个临时队列。
    • WMQ 重用临时队列并且一切都在内存中,因此获取句柄非常快。不过,您需要密切关注 DLQ,因为如果您的应用在回复出现之前超时,回复将被路由到 DLQ。如果您希望为响应队列使用预定义的队列,那也可以。但是,如果多个实例使用同一个队列,您将需要按 Correlation ID 执行 GET。但是,如果消息是持久的,则需要预定义或永久动态队列。
    猜你喜欢
    • 1970-01-01
    • 2017-02-19
    • 2019-01-25
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 2020-09-29
    相关资源
    最近更新 更多