【问题标题】:IBM MQ.NET Send Message Asynchronously and Commit()IBM MQ.NET 异步发送消息并 Commit()
【发布时间】:2018-10-10 00:02:37
【问题描述】:

我尝试使用以下代码验证同时使用异步 Put()Commit() 的速度。问题是它的速度比仅使用异步Put() 或仅使用Commit() 慢十倍,这是没有意义的。

我错过了什么吗?

class AsyncProducerWithCommit 
    {
        private MQQueueManager _queueManager;
        private MQQueue _queue;

        public void Run()
        {
            Produce();
        }


        void Produce()
        {
            Open(ConnectionMode.Write);

            PutMessage(ConvertMessageToByte(message)); 

            _queue.Close();
            _queueManager.Disconnect();
        }

        void PutMessage(byte[] messageString)
        {          
            MQMessage _message = new MQMessage();
            _message.Write(messageString);
            _message.Format = MQC.MQFMT_STRING;
            _message.CharacterSet = 1208;// IbmUtf8Encoding;
            _message.Persistence = MQC.MQPER_PERSISTENT;

            var putMessageOptions = new MQPutMessageOptions();
            putMessageOptions.Options  =  MQC.MQPMO_SYNCPOINT    //unit of work
                                          + MQC.MQPMO_ASYNC_RESPONSE;  //async

            _queue.Put(_message, putMessageOptions); //send message asynchronously

             _queueManager.Commit();   

        }

        void Open(ConnectionMode connectionMode)
        {
            string _queueManagerName = _appSetting.MessagingServerSetting.QueueManagerName;

            int openOptions = 0;

            switch (connectionMode)
            {
                case ConnectionMode.Read:
                    openOptions = MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING;
                    break;
                case ConnectionMode.Write:
                    openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;
                    break;
            }


            var properties = new Hashtable
            {
                {MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED },
                {MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT },
                { MQC.HOST_NAME_PROPERTY, "192.168.1.10" },
                { MQC.PORT_PROPERTY, "1415"},
                { MQC.CHANNEL_PROPERTY, "LOCAL.DEF.SVRCONN" },
                {MQC.USER_ID_PROPERTY, "user" },
                {MQC.PASSWORD_PROPERTY, "pwd" }               
            };

            _queueManager = new MQQueueManager(_queueManagerName, properties);
            _queue = _queueManager.AccessQueue(QUEUE_NAME, openOptions);
        }


        public enum ConnectionMode
        {
            Read,
            Write
        }

    }

更新 1

异步放置

 putMessageOptions.Options  =  MQC.MQPMO_ASYNC_RESPONSE;  //async
_queue.Put(_message, putMessageOptions); //send message asynchronously

提交提交

 putMessageOptions.Options  =  MQC.MQPMO_SYNCPOINT;    //unit of work                                         
  _queue.Put(_message, putMessageOptions); 
 _queueManager.Commit(); 

QueueManager 版本:Redhat Linux 7+ 上的 8.0.0.5

MQ.NET:8.0.0.8

【问题讨论】:

  • 您使用的是哪个 mq 队列管理器版本和 .net dll 版本?异步 put 仅影响将立即返回的 put 调用,而不是等待 qmgr 响应成功或失败。您能否展示您的程序的三个版本并提供每个版本的时间?
  • 请参阅更新 1。同样,它比 OP 中提到的慢十倍(例如 3 秒 vs 30 秒),这是相对的。
  • 另一个问题是 MQ.NET: 8.0.0.8 比 MQ.NET: 8.0.0.5 慢。任何想法?例如,3 秒 vs 5 秒

标签: c# ibm-mq


【解决方案1】:

在 IBM MQ v8 知识中心页面“Using asynchronous put in a client application”中声明:

通常,当应用程序将一条或多条消息放入队列时, 使用 MQPUT 或 MQPUT1,应用程序必须等待队列 经理确认它已处理 MQI 请求。你可以 提高消息传递性能,特别是对于使用 客户端绑定,以及将大量小 消息到队列,而是选择放置消息 异步。当应用程序异步发送消息时, 队列管理器不会返回每次调用的成功或失败,而是 您可以改为定期检查错误。

异步 ​​put 仅影响 put 调用,该调用将立即返回,而不是等待队列管理器确认它已处理 put。

因此,如果您有以下内容,那么它将是最快的,因为您永远不会等待消息写入磁盘。

_message.Persistence = MQC.MQPER_PERSISTENT;
putMessageOptions.Options  =  MQC.MQPMO_ASYNC_RESPONSE;  //async
_queue.Put(_message, putMessageOptions); //send message asynchronously

如果您有其中任何一个,则提交将等待消息写入磁盘,因此与磁盘写入所需的速度一样慢。这很可能比上面的要慢,但是 3sec vs 30sec 似乎并不合理。

_message.Persistence = MQC.MQPER_PERSISTENT;
putMessageOptions.Options  =  MQC.MQPMO_SYNCPOINT    //unit of work
                            + MQC.MQPMO_ASYNC_RESPONSE;  //async
_queue.Put(_message, putMessageOptions); //send message asynchronously
_queueManager.Commit();

或者

_message.Persistence = MQC.MQPER_PERSISTENT;
putMessageOptions.Options  =  MQC.MQPMO_SYNCPOINT;    //unit of work                                         
_queue.Put(_message, putMessageOptions); 
_queueManager.Commit(); 

如果使用 MQPMO_SYNCPOINT 和 MQPMO_ASYNC_RESPONSE 的调用是 30 秒,而仅使用 MQPMO_SYNCPOINT 的调用是 3 秒,那么我认为一定有某种缺陷,我建议你与 IBM 开一个 PMR,他们可能会要求你至少同时有一个客户端 .NET 跟踪和可能的队列管理器跟踪。

【讨论】:

  • 很好的回复。如何使用 IBM 打开 PMR?请提供这个的链接?如果可能的话,是否可以提供指向您提供的解释的链接?
  • 添加了对 IBM KC 的引用。根据贵公司与 IBM 签订的支持合同,将与 IBM 建立 PMR。有一个名为 SR 的在线站点可让您执行此操作,但您必须拥有 IBM 客户编号和有权打开这些请求的 IBM ID:ibm.com/support/servicerequest
  • @pingpong 如果您还有其他问题,请告诉我。
  • 我在两天前将帖子标记为答案,不知道为什么它不起作用。我现在又做了一次。
猜你喜欢
  • 2011-04-05
  • 2023-02-10
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 2012-12-23
  • 2015-01-09
  • 2019-08-29
相关资源
最近更新 更多