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

IBM MQ (iSeries) - Completion Code Defaulting to Zero?

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

此应用程序每天将数万条消息放在 iSeries MQ 上,全天候运行,并且已经可靠且有弹性地运行了 5 年。

昨天没有从 iSeries 端收到放在 MQ 上的 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. 检查完成代码 这是一个整数,因此默认为零,顺便说一句= MQCC_OK

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

现在,在 .NET Framework 中,INT 是一个结构,默认为 0,所以如果 MQ 没有发送完成代码,我们似乎有一个 MQCC_OK

那么,是否有可能消息在 MQ 上被拒绝或失败,但是因为我们有一个默认为零的 INT,我们似乎已经从 OK微商? client/server 与握手之间的安全通信肯定会阻止这种情况发生吗?

如果可能(尽管不太可能),我们如何才能防止这种情况发生?我在数据库中将 5 条消息标记为 Complete 基于 MQC.MQCC_OK但是 iSeries 似乎没有收到它们(同样,代码 运行 好几年了)

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

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

顺便说一句,如果出现任何异常,您在 Put 调用(如下所示)之后的代码将不会执行。此外,如果 Put 调用 returns 成功,则不需要检查完成代码,您可以简单地更新数据库。

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 */

当您执行 put() 方法时,您不应该检查 MQQueue class 的 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;
   }
}

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

DISPLAY QLOCAL(q-name) DEFPRESP