我们有一个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;
}
}
所以过程是:
对于每一个,创建一个MQ消息并将其放在队列
检查完成代码 这是一个INT,因此默认为ZERO,BTW = MQCC_OK
更新数据表,如果完成代码 = MQCC_OK ,我们假设收到的消息没有错误,否则我们更新该消息的数据表使用MQ警告消息或失败消息...
现在,在.NET Framework中,INT是STRUCT,默认为0,因此如果MQ没有发送COMPLETION CODE,我们似乎有一个MQCC_OK
那么,是否有可能在MQ上拒绝或失败消息,但由于我们将INT默认为零,我们似乎从MQ收到了 OK ?当然,客户端/服务器与握手之间的安全通信会阻止这种情况吗?
如果可能(但不太可能),我们如何防止这种情况,我在数据库上标记了5条消息,基于MQC.MQCC_OK 完成,但iSeries没有&#39;似乎已收到它们(再次,代码运行了几年)
答案 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