【问题标题】:Reusing a MQQueueManger in a Distributed Transaction in .NET在 .NET 的分布式事务中重用 MQQueueManger
【发布时间】:2016-11-16 14:27:33
【问题描述】:

我正在使用TransactionScope [.Net transactions] 编写一个 .NET 应用程序。代码是一个使用相同MQQueueManager 实例的简单循环:

  • 从主题订阅中接收
  • 保存到 MSSQL 数据库
  • 将翻译后的消息发送到另一个主题
  • 提交交易

当我到达循环顶部以获取新消息时,我收到了 MQRC_GLOBAL_UOW_CONFLICT 异常。

我了解事务提交是异步的,队列管理器可能尚未准备好参与新事务。我如何确定它已准备就绪?我在Transaction.Current 上订阅了TransactionCompleted 事件,并在重新进入循环之前等待它触发。同样的例外。我可以通过休眠 10 毫秒来避免异常,但我不想为此设置硬超时。必须有一个“正确”的方式来知道。

代码:

class Program
{
    public static bool tranDone = false;

    static void Main(string[] args)
    {
        Hashtable properties = new Hashtable();
        properties.Add(MQC.HOST_NAME_PROPERTY, "server");
        properties.Add(MQC.PORT_PROPERTY, 1414);
        properties.Add(MQC.CHANNEL_PROPERTY, "SYSTEM.DEF.SVRCONN");
        properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
        MQQueueManager mgr = new MQQueueManager("QManager", properties);

        MQTopic topicIn = mgr.AccessTopic("TopicString", "TopicName",
            MQC.MQSO_DURABLE | MQC.MQSO_RESUME | MQC.MQSO_MANAGED | MQC.MQSO_FAIL_IF_QUIESCING,
            null, "SubscriptionName");

        MQTopic topicOut = mgr.AccessTopic(
            "TopicString2", "TopicName",
            MQC.MQTOPIC_OPEN_AS_PUBLICATION,
            MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING);

        MQGetMessageOptions gmo = new MQGetMessageOptions
        {
            Options = MQC.MQGMO_WAIT | MQC.MQGMO_SYNCPOINT,
            // 1 minute wait
            WaitInterval = 1000 * 60
        };


        MQPutMessageOptions pmo = new MQPutMessageOptions
        {
            Options = MQC.MQPMO_SYNCPOINT,
        };



        while (true)
        {
            try
            {
                using (TransactionScope ts = new TransactionScope())
                {
                    Transaction.Current.TransactionCompleted += Current_TransactionCompleted;

                    MQMessage msgIn = new MQMessage();

                    topicIn.Get(msgIn, gmo);
                    string text = msgIn.ReadString(msgIn.MessageLength);
                    Console.WriteLine($"Message Received: {text}");

                    MQMessageContext context = new MQMessageContext();
                    context.Messages.Add(new Message() { Content = text });
                    context.SaveChanges();
                    Console.WriteLine("Added to DB");

                    MQMessage msgOut = new MQMessage();
                    string ttext = $"translated: {text}";
                    msgOut.WriteString(ttext);
                    topicOut.Put(msgOut, pmo);
                    Console.WriteLine($"Message Sent: {ttext}");

                    msgIn.ClearMessage();

                    Console.Write("Commit? [Y/N/Q]: ");
                    string response = Console.ReadLine();

                    if ("y" == response.ToLower())
                    {
                        ts.Complete();
                        Console.WriteLine("Transaction Committed");
                    }
                    else if ("q" == response.ToLower())
                    {
                        Console.WriteLine("Quitting");
                        break;
                    }
                }
            }
            catch (MQException mqe)
            when (MQC.MQRC_NO_MSG_AVAILABLE == mqe.ReasonCode)
            {
                Console.WriteLine("Msg not available in interval");
                continue;
            }

            while (!tranDone)
            {
                Thread.Sleep(2);
            }

            tranDone = false;
        }

    }

    private static void Current_TransactionCompleted(object sender, TransactionEventArgs e)
    {
        tranDone = true;
    }


}

【问题讨论】:

  • 发布您的代码可能有助于更好地理解问题
  • 除了 MQ 之外,您还为您的全局事务添加了哪些其他资源?即为什么您使用全局事务而不是仅 MQ 事务?
  • @MoragHughson Microsoft SQLServer。 MQMessageContext 携带数据库连接并在 context.SaveChanges() 上提交
  • @Shashi。我没有连接到队列管理器的问题。不确定要在您链接的页面中查找什么。

标签: .net transactions ibm-mq


【解决方案1】:

连接句柄(或 HCONN)基本上表示与队列管理器的连接。它由 OO 语言(如 C#)中的 MQQueueManager 类抽象出来。像 C 这样的语言提供了对 HCONN 的访问。

MQ 以每个连接为基础跟踪事务。所以我给你的建议是为每笔交易创建一个新的连接以避免MQRC_GLOBAL_UOW_CONFLICT 错误。完成交易后请务必关闭连接。

【讨论】:

  • 重新连接和重新访问主题和订阅的成本是多少?
  • 现有对象肯定会涉及成本,需要关闭连接并为每个新事务创建新对象。
猜你喜欢
  • 2011-05-15
  • 2012-09-03
  • 2020-03-26
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多