【问题标题】:Message Queue(MSMQ) does not throw exception when message is not received on the other end另一端未收到消息时,消息队列(MSMQ)不抛出异常
【发布时间】:2013-07-12 19:57:49
【问题描述】:

假设我尝试发送到经过身份验证的事务队列,

通过调用msg.send(object,MessageQueueTransactionType.Single),事务队列中没有收到消息,没有抛出异常

我想要完成的是发送后,如果消息发送失败,执行一些功能并中止事务,但它没有抛出异常,所以我无法处理它。 p>

我正在从本地消息队列中的 Web 应用程序发送对象。

我的网络应用程序中的代码如下:

MessageQueueTransaction mqTran=new MessageQueueTransaction();

try
{
  using(System.Messaging.Message msg=new System.Messaging.Message(){
  mqTran.Begin();

  MessageQueue adminQ = new MessageQueue(AdminQueuePath);
  MessageQueue msgQ = new MessageQueue(queuePath);
  msgQ.DefaultPropertiesToSend.Recoverable = true;

  msg.body = object;
  msg.Recoverable=true;
  msg.Label="Object";
  msg.TimeToReachQueue=new TimeSpan(0,0,30);
  msg.AcknowledgeType=AcknowledgeTypes.FullReachQueue;
  msg.ResponseQueue=adminQ;
  msg.AdministrationQueue=adminQ;
  msgQ1.Send(msg,MessageQueueTransactionType.Single);
  mqTran.Commit();
}
catch(Exception e)
{
  mqTran.Abort();
  //Do some processing if fail to send
}

【问题讨论】:

  • “我正在从本地的 Web 应用程序向本地消息队列发送对象。”这是否意味着发送应用和接收队列在同一台机器上?
  • 是的,它们在同一台机器上,所以我应该实现 MSMQ 还是生成我自己生成的队列类?
  • MSMQ 没问题。只是底层过程非常不同。例如,没有传出队列。 Send() 会将消息直接放入目标队列,而不是放入中间传出队列以进行转发。如果发送失败,您将立即获得异常返回。你的 try/catch 应该在 send() 附近。

标签: msmq


【解决方案1】:

它不会因为未能交付而抛出异常,只会因为未能放入队列而引发异常。消息队列的要点之一是消息是持久的,因此如果传递失败,您可以采取适当的措施。这意味着您需要编写另一个进程来读取死信队列。下图取自MSDN

因为整个过程是异步的,所以您的代码流不会像您的代码块所希望的那样由异常驱动。您的交易只是此工作流程中的“发送交易”。

建议:检查您的消息队列以在传出队列或事务性死信队列中查找消息。

【讨论】:

  • 那么我应该如何在我的代码中实现它?假设有多个应用程序同时发送到同一个消息队列,我无法真正检查死信队列属于哪个应用程序。
  • 假设在发送后我再添加一条语句:msgQ1.PeekById(msg.Id);
  • 抱歉,澄清一下,我的“建议”是指故障排除,而不是编码解决方案。为此,您可能需要创建一个单独的 Windows 服务,该服务会定期查看队列,并在备份过多时发送警报消息。
  • 所以如果 msg 无法发送到 dest,它肯定会在死 msg 队列中并且不会丢失?我想知道的是有保证不会丢失数据
  • 不,发送到本地队列失败意味着消息一开始就无法创建,您会遇到异常。死信队列用于可以创建但最终传递失败的消息。
猜你喜欢
  • 2021-12-05
  • 2012-02-06
  • 2012-05-22
  • 1970-01-01
  • 2018-02-20
  • 2017-11-11
  • 2011-05-01
  • 2012-02-12
  • 1970-01-01
相关资源
最近更新 更多