在向MQ Topic发布消息时是否可以使用内置关联?

时间:2011-11-10 15:44:44

标签: java .net publish-subscribe ibm-mq

我在使用WebSphere MQ 7中的主题时有点迷失。假设简单的场景:

  • 我有一个流程将消息发布到主题。
  • 我有零个或多个订阅者收到该消息。
  • 任何订阅者都可以决定对收到的消息做出反应=可选“回复”。 (旁注:最初的决定是使用主题进行回复,但我会在必要时将其更改为队列)已发布的消息可以配置为ReplyToQueueName,也可以是客户端上的系统级配置。
  • 响应必须与原始发布的“请求”相关联(因为可能有多个已发布的请求)。

现在怎么做?我尝试使用MQ队列中的通用方法,其中发起者选择:

  • 将报告设为MQRO_COPY_MSG_ID_TO_CORREL_ID。 Receiver将从请求中获取消息ID,并将其作为响应中的相关ID传递。
  • 将报告设置为MQRO_PASS_CORREL_ID +在请求消息中设置关联ID。接收方将从请求中获取相关ID,并在响应消息中将其设置为相关ID。

在这两种情况下,发件人都知道传递给请求的消息ID或相关ID,因此它可以正确地关联消息,但这不适用于MQ主题。

如果我尝试遵循上述方法,我在发布请求时会立即出现问题 - 发布方未设置消息ID(它为空),因此无法采用第一种方法。如果我尝试在发布者端设置相关ID,我将在订阅者端获得不同的,因此我不能将其用于消息关联(=第二种方法也不可能)。

以下是使用主题(ID在Base64中)时会发生什么的一些示例:

使用MQRO_COPY_MSG_ID_TO_CORREL_ID进行测试:

Send request: // After sending message publisher doesn't know its ID!
Message Id:     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Correlation Id: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Received request: // Subscriber gets some ID and correlation ID (but publisher didn't set any)
Message Id:     QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYH
Correlation Id: QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYF

Send response:  // Subscriber correctly uses message ID of incoming request
Message Id:     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Correlation Id: QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYH

Received response: // Publisher gets in response completely different IDs!
Message Id:     QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYP
Correlation Id: QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYN

使用MQRO_PASS_CORREL_ID进行测试:

Send request: // Publisher doesn't know its ID but it generated some random correlation ID.
Message Id:     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Correlation Id: Chhv8KT+zhTjfAEdzeiB3cizw9vRy9Pf

Received request: // Subscriber got ANOTHER correlation ID!
Message Id:     QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYY
Correlation Id: QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYW

Send response:  // Subscriber is using incorrect correlation ID.
Message Id:     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Correlation Id: QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYW

Received response: // Publisher gets in response completely different IDs!
Message Id:     QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYg
Correlation Id: QU1RIExNLnF1ZXVlLm1hbp2OiU4g6AYe

如何强制MQ不改变我的ID?我在Java和.NET中编写了测试应用程序,两者的行为方式相同。或者我的用例的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

您是否考虑过使用JMS(MQ作为实现)而不是MQ api直接编码?

JMS已经在已发布的消息中具有replyTo的概念,并且已经具有将correlation id链接在一起的概念{{3}}。对于replyTo,发布者可以指定队列或主题,因此您不会在接收端绑定任何一个。

答案 1 :(得分:2)

消息ID在消息传递系统中是唯一的。在发布/订阅模式中,消息传递引擎将发布者发送的消息的副本发布给多个(和未知的)订阅者。由于消息ID必须是唯一的,因此每条消息都将具有不同的消息ID。

编辑:

再次阅读信息中心,这是我找到的。

您可以使用MQSO_SET_CORREL_ID选项强制队列管理器保留应用程序设置的correlId。

int subOptions = MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_INPUT_SHARED | MQC.MQSO_SET_CORREL_ID;
MQTopic sub = qm.AccessTopic(recvQ, "/TEST/CORRELID", null, subOptions);

必须注意的是,如果您在创建订阅时使用MQSO_SET_CORREL_ID选项,则无法使用MQSO_MANAGED

发布时将correlID设置为

putMsg.CorrelationId = Encoding.ASCII.GetBytes("THISISTHECORRELID");
topicCorrelId.Put(putMsg);

接收发布时,您可以使用匹配的相关选项,如

gmo.MatchOptions = MQC.MQMO_MATCH_CORREL_ID;
fwdMsg.CorrelationId = Encoding.ASCII.GetBytes("THISISTHECORRELID"); 

sub.Get(fwdMsg, gmo);

仅当您使用队列进行多次订阅并且您只想获取特定主题的出版物时才使用MQMO_MATCH_CORREL_ID