IBM MQ(iSeries) - 完成代码默认为零?

时间:2015-07-28 13:34:48

标签: c# ibm-mq

我们有一个Windows c#应用程序,它将消息放在iSeries Websphere MQ队列上以进行核心系统处理。

该应用程序每天在iSeries MQ上放置数万条消息,全天候运行,并且可靠且有弹性5年。

昨天在iSeries方面没有收到5条消息(一批10条),但在我们这边,我们似乎有完成代码MQCC_OK(值= 0)

这是我们的代码:

foreach (DataRow dRow in mqRequests.Rows)
{
     try
         {
          queuePutMessage = new MQMessage();
         queuePutMessageOptions = new MQPutMessageOptions();
         queuePutMessage.WriteString(dRow[(int)Common.InboundSQLFields.EDB_Message].ToString());                    
        queuePutMessage.Format = MQC.MQFMT_STRING; // MQFMT_STRING = "MQSTR   ";

        /* Put message on Queue */
        pMQQueue.Put(queuePutMessage, queuePutMessageOptions);

        switch (pMQQueue.CompletionCode){

            case MQC.MQCC_OK:
            /* Message successfully PUT on return MQ */
            dRow[(int)Common.InboundSQLFields.MQ_Put_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
            dRow[(int)Common.InboundSQLFields.Message_Status] = "Complete";
            dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
            break;

            case MQC.MQCC_WARNING:
            //  with warning
            dRow[(int)Common.InboundSQLFields.Message_Status] = "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName;
            dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");

            /* Write to log */
            Common.logBuilder("WebSphereMQ --> putMessages <--", "MQWarning", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
             emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName);
             break;

             case MQC.MQCC_FAILED:

                 dRow[(int)Common.InboundSQLFields.Message_Status] = "Error:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName;
                 dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");

                  /* Write to log */
                  Common.logBuilder("WebSphereMQ --> putMessages <--", "MQFAIL", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
                  emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName);
                  break;
                  }
            }
            catch (MQException mqe)
            {
                dRow[(int)Common.InboundSQLFields.Message_Status] = "Error";
                dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
                /* Write to log */
                Common.logBuilder("WebSphereMQ --> putMessages <--", "MQException", Common.ActiveMQ, mqe.Message, "Exception");
                emailer.exceptionEmail(mqe);

                // Return nothing
                return;
            }
            catch (Exception ex)
            {
                dRow[(int)Common.InboundSQLFields.Message_Status] = "Error";
                dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
                /* Write to log */
                Common.logBuilder("WebSphereMQ --> putMessages <--", "Exception", Common.ActiveMQ, ex.Message, "Exception");
                emailer.exceptionEmail(ex);
                // Return nothing
                return;
            }
        }

所以过程是:

  1. 遍历要放在MQ上的所有消息
  2. 对于每一个,创建一个MQ消息并将其放在队列

  3. 检查完成代码 这是一个INT,因此默认为ZERO,BTW = MQCC_OK

  4. 更新数据表,如果完成代码 = MQCC_OK ,我们假设收到的消息没有错误,否则我们更新该消息的数据表使用MQ警告消息或失败消息...

  5. 现在,在.NET Framework中,INT是STRUCT,默认为0,因此如果MQ没有发送COMPLETION CODE,我们似乎有一个MQCC_OK

    那么,是否有可能在MQ上拒绝或失败消息,但由于我们将INT默认为零,我们似乎从MQ收到了 OK ?当然,客户端/服务器与握手之间的安全通信会阻止这种情况吗?

    如果可能(但不太可能),我们如何防止这种情况,我在数据库上标记了5条消息,基于MQC.MQCC_OK 完成,但iSeries没有&#39;似乎已收到它们(再次,代码运行了几年)

3 个答案:

答案 0 :(得分:1)

如果在放置消息时出现任何错误,则会抛出MQ异常并且您拥有捕获任何MQException的代码。因此,客户端应用程序极不可能丢失队列管理器发送的错误。

您使用的是什么版本的MQ客户端?

BTW你在Put调用之后所拥有的代码(如下所示)在任何异常情况下都不会执行。此外,如果Put调用成功返回,则无需检查完成代码,您只需更新数据库即可。

switch (pMQQueue.CompletionCode){

        case MQC.MQCC_OK:
        /* Message successfully PUT on return MQ */
        dRow[(int)Common.InboundSQLFields.MQ_Put_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
        dRow[(int)Common.InboundSQLFields.Message_Status] = "Complete";
        dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
        break;

        case MQC.MQCC_WARNING:
        //  with warning
        dRow[(int)Common.InboundSQLFields.Message_Status] = "Warning:\t" + pMQQueue.ReasonCode + '\t' + pMQQueue.ReasonName;
        dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");

        /* Write to log */

答案 1 :(得分:1)

执行put()方法时,不应检查MQQueue类的CompletionCode。代码应如下所示:

foreach (DataRow dRow in mqRequests.Rows)
{
   try
   {
      outMsg = new MQMessage();
      pmo = new MQPutMessageOptions();
      outMsg.WriteString(dRow[(int)Common.InboundSQLFields.EDB_Message].ToString());
      outMsg.Format = MQC.MQFMT_STRING; // MQFMT_STRING = "MQSTR   ";

      /* Put message on Queue */
      pMQQueue.Put(outMsg, pmo);

      dRow[(int)Common.InboundSQLFields.MQ_Put_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
      dRow[(int)Common.InboundSQLFields.Message_Status] = "Complete";
      dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
   }
   catch (MQException mqe)
   {
      switch (mqe.CompletionCode)
      {
         case MQC.MQCC_WARNING:
            //  with warning
            dRow[(int)Common.InboundSQLFields.Message_Status] = "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode;
            dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");

            /* Write to log */
            Common.logBuilder("WebSphereMQ --> putMessages <--", "MQWarning", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
            emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
            break;

         case MQC.MQCC_FAILED:

            dRow[(int)Common.InboundSQLFields.Message_Status] = "Error: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode;
            dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");

            /* Write to log */
            Common.logBuilder("WebSphereMQ --> putMessages <--", "MQFAIL", Common.ActiveMQ, dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), "Exception");
            emailer.messageMonitorEmail(dRow[(int)Common.InboundSQLFields.Message_Type].ToString(), Common.ActiveMQ, "Warning: CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
            break;
      }

      /* Write to log */
      Common.logBuilder("WebSphereMQ --> putMessages <--", "MQException", Common.ActiveMQ, mqe.Message, "CC=" + mqe.CompletionCode + ' : RC=' + mqe.ReasonCode);
      emailer.exceptionEmail(mqe);

      // Return nothing
      return;
   }
   catch (Exception ex)
   {
      dRow[(int)Common.InboundSQLFields.Message_Status] = "Error:\t" + ex.Message;
      dRow[(int)Common.InboundSQLFields.Last_Modified_Date] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
      /* Write to log */
      Common.logBuilder("WebSphereMQ --> putMessages <--", "Exception", Common.ActiveMQ, ex.Message, "Exception");
      emailer.exceptionEmail(ex);
      // Return nothing
      return;
   }
}

答案 2 :(得分:0)

您可以看到的行为可能由具有设置DEFPRESP(ASYNC)的目标队列解释。此设置意味着在请求失败之前不会将故障发送回应用程序,从而加快了通过客户端发送多个消息的速度。如果应用程序不期望该行为,则不应该使用它。这将是一个快速检查,以确定是否在您的系统中设置了这个。

DISPLAY QLOCAL(q-name) DEFPRESP