gpt4 book ai didi

c# - WebSphere MQ/C# 订阅 : topic GET hangs forever

转载 作者:行者123 更新时间:2023-12-02 21:02:33 25 4
gpt4 key购买 nike

  1. 我正在尝试在 C#/.Net 应用程序中实现 MQ 发布/订阅。

  2. 我已按照本教程中的说明进行操作:

    https://tekslate.com/publish-subscribe-in-websphere-mq-series/

    • a) 队列管理器:QM
    • b) TCP 监听器正在运行,端口:1420
    • c) 主题名称:NEWS.SPORTS.CRICKET
    • d) 订阅名称也:NEWS.SPORTS.CRICKET
    • e) 主题字符串:NEW/SPORTS/CRICKET
    • f) 目的地队列:SportsQ
  3. 我成功地在 MQ Explorer 中进行“测试发布”。我在订阅中看到“消息计数 = 1”。我在 SportsQ 中看到“队列深度 = 1”

  4. 我能够连接到 QM,我能够访问该主题...但当我执行“topic.Get(message”) 时它就会挂起

问:为什么 MQ“Get()”挂起??????

代码:

using IBM.WMQ;
using System;
using System.Collections;

namespace HelloSubscribe
{
class Program
{
static void Main(string[] args)
{
string qmName = "QM";
string hostName = "localhost";
string strPort = "1420";
string channelName = "SYSTEM.DEF.SVRCONN";
string transport = MQC.TRANSPORT_MQSERIES_CLIENT;

Hashtable connectionProperties = new Hashtable();
connectionProperties.Add(MQC.HOST_NAME_PROPERTY, hostName);
connectionProperties.Add(MQC.PORT_PROPERTY, strPort);
connectionProperties.Add(MQC.CHANNEL_PROPERTY, channelName);

MQQueueManager mqQueueManager = new MQQueueManager(qmName, connectionProperties);

string topicObject = null;
string topicString = "NEWS/SPORTS/CRICKET";
string subscriptionName = "NEWS.SPORTS.CRICKET";
string topicName = "NEWS.SPORTS.CRICKET";
int openOptionsForGet = MQC.MQSO_CREATE | MQC.MQSO_FAIL_IF_QUIESCING | MQC.MQSO_DURABLE | MQC.MQSO_RESUME;
MQTopic destForGet = mqQueueManager.AccessTopic(topicString, null, openOptionsForGet, null, subscriptionName);

MQMessage messageForGet = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.WaitInterval = 1000; // wait 60 seconds
destForGet.Get(messageForGet, gmo);
string msg = messageForGet.ReadLine();

destForGet.Close();
mqQueueManager.Disconnect();
mqQueueManager.Close();
}
}
}

我正在运行 WebSphere MQ 7.5,使用已安装的 amqdnet.dll 版本和 Visual Studio 2015。

最佳答案

MQ 管理订阅

您引用的教程设置了 MQ 管理订阅来将主题字符串订阅到特定的 MQ 队列,这样,发布到与订阅的主题字符串匹配的主题的任何消息都将被放入您在 MQ 上指定的队列管理订阅例如SportsQ ,要从队列中读取消息,您可以将其视为队列而不是主题,并使用 AccessQueue 访问它。方法举例:

        string queueName = "SportsQ";
int openOptionsForGet = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_FAIL_IF_QUIESCING;
MQQueue destForGet = mqQueueManager.AccessQueue(queueName, openOptionsForGet, null, null, null);
<小时/>

托管持久订阅

您在提供的代码中演示的内容称为托管持久订阅,在后台 MQ 将创建一个前缀为 SYSTEM.MANAGED.DURABLE.<uniq 16 character HEX value> 的队列。并将其订阅到主题字符串。如果您断开连接,然后使用相同的“订阅名称”恢复,那么您将连接到同一个托管队列,并接收在未连接时发布的任何消息。

请注意,除了所谓的“保留发布”(其中 MQ 将为 future 订阅者保存最新发布)之外,您在订阅之前不会收到发布到主题字符串的任何消息,这就是为什么您看不到您想要的消息的原因。在创建托管持久订阅之前通过 MQ Explorer 发布。

根据您提供的内容,您应该能够向主题字符串发布新消息,您的应用程序就会收到它。

<小时/>

非托管持久订阅

另一个选项是删除您创建的 MQ 管理订阅并更改您的程序以在您提供队列目标的情况下进行非托管订阅,例如:

        string queueName = "SportsQ";
int QueueOpenOptionsForGet = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_FAIL_IF_QUIESCING;
int TopicOpenOptionsForGet = MQC.MQSO_CREATE | MQC.MQSO_FAIL_IF_QUIESCING | MQC.MQSO_DURABLE | MQC.MQSO_RESUME;
MQQueue destQueue = mqQueueManager.AccessQueue(queueName, QueueOpenOptionsForGet);
MQTopic destForGet = mqQueueManager.AccessTopic(destQueue, topicString, null, openOptionsForGet, null, subscriptionName);

这会导致创建一个 API 订阅,将主题字符串链接到您提供作为目标的队列。

就像 MQ 管理订阅一样,您可以将其视为要从中获取的队列,或者您可以恢复订阅。

<小时/>

恢复非托管持久订阅而无需知道队列名称

您仍然需要调用以目标作为第一个参数的 AccessTopic 重载,但您传入 NULL 而不是 MQDestination,程序将恢复已创建的非托管订阅,而无需知道队列名称。我能够编译并测试以下内容是否有效:

using IBM.WMQ;
using System;
using System.Collections;


namespace HelloSubscribe
{
class Program
{
static void Main(string[] args)
{
string qmName = "QM";
string hostName = "localhost";
string strPort = "1420";
string channelName = "SYSTEM.DEF.SVRCONN";
string transport = MQC.TRANSPORT_MQSERIES_CLIENT;

Hashtable connectionProperties = new Hashtable();
connectionProperties.Add(MQC.HOST_NAME_PROPERTY, hostName);
connectionProperties.Add(MQC.PORT_PROPERTY, strPort);
connectionProperties.Add(MQC.CHANNEL_PROPERTY, channelName);

MQQueueManager mqQueueManager = new MQQueueManager(qmName, connectionProperties);

string topicString = "NEWS/SPORTS/CRICKET";
string subscriptionName = "NEWS.SPORTS.CRICKET";
int openOptionsForGet = MQC.MQSO_FAIL_IF_QUIESCING | MQC.MQSO_DURABLE | MQC.MQSO_RESUME;
MQTopic destForGet = mqQueueManager.AccessTopic(null, topicString, null, openOptionsForGet, null, subscriptionName);

MQMessage messageForGet = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.WaitInterval = 60000; // wait 60 seconds
destForGet.Get(messageForGet, gmo);
string msg = messageForGet.ReadLine();
System.Console.WriteLine("Received message data : " + msg);

destForGet.Close();
mqQueueManager.Disconnect();
mqQueueManager.Close();
}
}
}

另请注意,您甚至不需要 topicString,它也可以为 null,subscriptionName 就是恢复它所需的全部内容:

            MQTopic destForGet = mqQueueManager.AccessTopic(null, null, null, openOptionsForGet, null, subscriptionName);
<小时/>

其他一些注意事项,教程中的示例提供了混合大小写的队列名称,不建议这样做,因为在许多地方,如果您不小心,IBM MQ 会将内容折叠为大写。推荐的最佳实践是对 IBM MQ 对象名称(队列等)使用大写。

WaitInterval 以毫秒为单位,因此将其设置为 1000 将等待 1 秒而不是 60 秒。

关于c# - WebSphere MQ/C# 订阅 : topic GET hangs forever,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47043778/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com