使用Windows服务和SQL Server在OneWay WCF消息中排队

时间:2012-03-14 12:55:00

标签: c# asp.net .net sql-server wcf

我需要为WCF服务请求实现排队机制。客户将以单向方式调用该服务。这些请求消息应存储在SQL Server数据库中,Windows服务将对消息进行排队。处理请求的时间是可配置的。如果在处理消息时发生错误,则需要重试最多100次,如果仍然失败则需要终止。

此外,应该有一种机制来监控一天的交易次数和失败次数。

问题

  1. 如果我使用的是MSMQ,客户端可能会在不知道服务端点的情况下将消息转发到队列。但我使用SQL Server来存储请求消息。客户端如何将请求发送到SQL Server?

  2. 解决方案是否可行?我们是否有任何文章/书籍解释如何实施上述内容?

  3. 在这种情况下,阻止服务和客户端到达故障状态的步骤是什么?

  4. 将传入消息存储到数据库的最佳方法是什么?

  5. 实施重试机制的最佳方法是什么?任何已经存在的东西,以便我不必重新发明轮子?

  6. 是否有任何书/文章解释此实施?


  7. 注意

    1. 邮件内容将是复杂的XML。例如,员工的旅行费用项目或员工列表。

    2. 阅读

      1. Logging WCF Request to Database

      2. Guaranteed processing of data in WCF service

      3. MSMQ vs. SQL Server Service Broker

      4. Is it possible to persist and then forward WCF messages to destination services?

      5. WCF 4 Routing Service - protocol bridging issue

      6. https://softwareengineering.stackexchange.com/questions/134605/designing-a-scalable-and-robust-retry-mechanism

      7. Integrating SQL Service Broker and NServiceBus

      8. Can a subscriber also publish/send message in NServiceBus?

3 个答案:

答案 0 :(得分:3)

我是一名DBA,因此我的回答有点味道,但这就是我要做的事情:

  1. 如果您使用的是SQL 2005+,请使用Service Broker存储消息 在数据库中而不是将它们存储在表中。你得到一个 这个排队机制,所以你可以摆脱MSMQ。您还将拥有一个表,但它只是存储会话句柄(本质上是指向消息的指针)以及它尝试此消息的次数。最后,您需要某种“死信箱”,其中包含达到您的重试阈值的消息。
  2. 在邮件处理代码中,执行以下操作:
    • 开始交易
    • 从队列中接收消息
    • 如果重试次数大于阈值,请将其移至死信框并提交
    • 为此消息增加表格上的计数器
    • 处理消息
    • 如果处理成功,请提交交易
    • 如果处理失败,请在队列中添加具有相同内容的新消息,然后提交事务
  3. 请注意,没有任何计划的回滚。 Service Broker中的回滚可能很糟糕;如果在没有成功接收的情况下回滚5次,则队列将因排队和出列而被禁用。但是,当您的消息处理器在处理过程中死亡(即服务器崩溃)时,您仍希望获得事务处理。

答案 1 :(得分:2)

  

1。如果我使用的是MSMQ,客户端可能会在不知道服务端点的情况下将消息转发到队列。

是 - 但是他们需要知道 MSMQ端点才能将他们的消息发送到队列.....

  

但我使用SQL Server来存储请求消息。客户端如何将请求发送到SQL Server?

客户端不会将他们的请求放入SQL Server - 这就是服务器上的服务所做的事情。客户端只调用一个服务方法,其中的代码将请求存储到SQL Server表中。

  

2。解决方案可行吗?我们是否有任何文章/书籍解释如何实施上述内容?

当然,我没有看到任何大问题。我现在唯一不清楚的一点是:客户如何知道他们的结果?他们是否需要从其他服务或其他服务获得结果?

  

3。在这种情况下,阻止服务和客户端到达故障状态的步骤是什么?

一如既往 - 只需确保您的服务代码捕获所有异常并在内部处理它们,或者返回可互操作的SOAP错误而不是.NET异常。

答案 2 :(得分:2)

听起来你想要做的就是这样:

enter image description here

在这种情况下,您可以在服务和服务使用者之间使用netMsmqBinding。

你唯一不会开箱即用的是重试。但是,如果您将队列设置为事务性,则可以在服务代码中实现此功能。

如果您的出队操作失败,则不会从队列中删除该消息。因此,它可用于进一步的出队尝试。

但是,您需要实现重试尝试阈值代码,该代码在一定次数的尝试后失败。