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;
}
}
所以过程是:
- 遍历要放在 MQ 上的所有消息
为每一个创建一个 MQ 消息并将其放入队列
检查完成代码 这是一个整数,因此默认为零,顺便说一句= MQCC_OK
更新数据表,如果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
我们有一个 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;
}
}
所以过程是:
- 遍历要放在 MQ 上的所有消息
为每一个创建一个 MQ 消息并将其放入队列
检查完成代码 这是一个整数,因此默认为零,顺便说一句= MQCC_OK
更新数据表,如果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