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

Posted

技术标签:

【中文标题】使用 Windows 服务和 SQL Server 在 OneWay WCF 消息中排队【英文标题】:Queuing in OneWay WCF Messages using Windows Service and SQL Server 【发布时间】:2012-03-30 22:29:01 【问题描述】:

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

还应该有一种机制来监控一天的交易数量和失败的数量。

问题

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

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

    在这种情况下,防止服务和客户端进入故障状态的步骤是什么?

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

    实现重试机制的最佳方法是什么?任何东西已经存在,所以我不必重新发明***?

    是否有任何书籍/文章解释了这种实现?


注意事项

    消息的内容将是复杂的 XML。例如,员工的差旅费用项目或员工列表。

阅读

    Logging WCF Request to Database

    Guaranteed processing of data in WCF service

    MSMQ vs. SQL Server Service Broker

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

    WCF 4 Routing Service - protocol bridging issue

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

    Integrating SQL Service Broker and NServiceBus

    Can a subscriber also publish/send message in NServiceBus?

【问题讨论】:

很难理解你想做什么。您的客户正在调用服务,但也将请求放入 SQL 中?这没有多大意义。请求肯定会被服务消费。 Hey Lijo 最好使用 SQL“Servive Broker”,它可以很好地满足您的要求。我使用“ServiceBroker”解决了类似的情况。msdn.microsoft.com/en-us/library/ms166043(v=sql.90).aspx 【参考方案1】:

我是一名 DBA,所以我的回答很有趣,但我会这样做:

    如果您使用的是 SQL 2005+,请使用 Service Broker 来存储消息 在数据库中而不是将它们存储在表中。你得到一个 有了这个排队机制,就可以摆脱MSMQ了。您还将有一个表,但它只是要存储对话句柄(本质上是指向消息的指针)以及它尝试此消息的次数。最后,您需要某种“死信箱”,将达到重试阈值的邮件存放在其中。 在您的消息处理代码中,执行以下操作: 开始交易 从队列中接收消息 如果重试次数大于阈值,则将其移至死信箱并提交 为这条消息增加表格上的计数器 处理消息 如果处理成功,提交事务 如果处理失败,则在队列中放入一条内容相同的新消息,然后提交事务

请注意,没有任何计划的回滚。 Service Broker 中的回滚可能很糟糕;如果您在没有成功接收的情况下回滚 5 次,则队列将在入队和出队时都被禁用。但是您仍然希望在消息处理器在处理过程中死机(即服务器崩溃)的情况下进行事务处理。

【讨论】:

感谢死信队列的概念【参考方案2】:

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

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

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

客户端不会将他们的请求放到 SQL Server 中——服务器上的服务会这样做。客户端只要调用一个服务方法,里面的代码就会把请求存入SQL Server表中。

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

当然,我看不出有什么大问题。我现在唯一不清楚的一点是:客户如何知道他们的结果?他们是否需要从其他服务或其他东西中获取结果??

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

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

【讨论】:

谢谢。我对这些想法完全陌生。将传入消息存储到数据库中的最佳方法是什么? @Lijo:完全取决于消息.....是什么构成了您的消息?一些字符串?很复杂的 XML 结构?? 复杂的 XML。例如员工的差旅费用项目或员工列表 @Lijo:如果您将处理来自队列的消息的服务可以直接处理 XML - 只需将复杂的 XML 存储在 SQL Server 表中即可。这是迄今为止最简单的方法。 @Lijo:好吧,你必须有一个可以调用的 WCF 服务,例如HTTP。该方法的服务代码需要接受您需要的参数,并且需要以某种方式(ADO.NET 或实体框架或其他)将该数据存储到数据库表中。一旦它在数据库中,需要一些其他的过程来抓取它并处理它——把它变成报告、PDF或返回消息——或者你想要的任何东西.....真的很难解释多久当你自己如此不清楚时。 ....【参考方案3】:

听起来你想做的和这个类似:

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

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

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

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

【讨论】:

谢谢。但是,我正在寻找稍微不同的场景 - 将消息存储到数据库。我已经更新了这个问题。您能否提供更多见解? 很抱歉,您的问题仍然没有意义。我不明白为什么必须将消息存储在数据库中,然后让 Windows 服务将它们放入队列中。同时,您有客户调用服务。它没有挂在一起。也许您可以创建一个新问题来描述您的业务需求,我们可以从那里着手。【参考方案4】:

我会建议与此处建议的方法不同的方法。如果可以的话,我会考虑引入一个消息传递框架,例如NServiceBus。它满足您开箱即用的许多要求。让我尝试根据您的要求解决这个问题。

服务将以单向方式被客户端调用。

NServiceBus 中端点之间的所有通信都是一种方式。 NServiceBus 使用的底层传输是 MSMQ,与您的 WCF 方法非常相似,您的客户端与队列通信,而不是与特定的服务端点通信。

这些请求消息应存储在 SQL Server 数据库中,并由 Windows 服务对消息进行排队。

如果您想将请求消息存储在数据库中,那么您可以配置 NServiceBus 以将发送到您的请求处理端点的所有消息转发到另一个“审核”队列,您可以使用该队列将其持久保存到数据库中。这具有将应用程序逻辑与审计实现分开的额外好处。

处理请求的时间是可配置的。

NServiceBus 允许您延迟发送消息。通常,消息通过 Bus 实例的 Send 方法发送 - Bus.Send(msg)。您可以使用 The Defer 方法在将来的某个时间发送消息,例如。 Bus.Defer(DateTime.Now.AddDays(1), msg);您无需再做任何事情,NserviceBus 会在到达指定时间后处理消息。

如果处理消息时出现错误,最多需要重试100次,如果仍然失败则需要终止。

默认情况下,一旦您的消息离开队列,NServiceBus 就会在事务中登记您的消息。这可确保在发生故障时将消息回滚到原始队列。在这种情况下,NServiceBus 将自动尝试以可配置的次数重新处理消息。默认值为 5。当然,您可以将其设置为您想要的任何值,尽管我不确定您为什么要将其设置为 100。无论如何,NServiceBus 使用此设置来停止自动重试的无限循环。一旦达到限制,消息就会被发送到错误队列,直到您修复任何导致异常的问题或直到您决定将消息推回队列进行处理。无论哪种方式,您都可以确保消息永远不会丢失。

还应该有一个机制来监控一天的交易数量和失败的数量。

使用 MSMQ 作为传输的美妙之处在于可以在基础架构级别实现性能监控。您的应用程序的执行情况可以通过它们在队列中的等待时间来衡量。 NServiceBus 带有性能监视器,可以跟踪消息在队列中的时间长度,您还可以添加内置到窗口中的 perf mons 以跟踪其他活动。要监控错误,您只需检查错误队列中的消息数即可。

NServiceBus 的主要特性之一是可靠性。 WCF 只会为你做这么多,然后你就靠你自己了。这是大量的代码、复杂性和坦率地说非常容易出错。我在这里描述的东西都是 NServiceBus 的标准特性,我几乎没有触及到你可以用它做的所有其他事情的表面。我建议你检查一下。

【讨论】:

谢谢。看起来很有希望。如果我还有任何问题,我会通知您。 但是,我无法在我的项目中使用它,因为它需要使用 WCF 进行开发。 如果需要,您仍然可以在客户端使用 WCF。让处理您的消息的服务器组件公开一个 WCF 端点以供您的客户端进行交互。然后就可以使用 NServiceBus 来做消息的实际处理了。下载中有一个示例应用程序,显示了如何实现此目的的示例。不管怎样,祝你好运。

以上是关于使用 Windows 服务和 SQL Server 在 OneWay WCF 消息中排队的主要内容,如果未能解决你的问题,请参考以下文章

我的sql server 2008不能登录,用windows和sa都无法登录 标题: 连接到服务器 ---------------------------

SQL Server2005 windows身份验证无法登陆问题

使用 Windows XP 作为 SQL Server

windows不能在本地计算机启动server服务,无法启用共享服务

Windows Server 2008和Visual Studio 2008和SQL Server 2008是啥大神们帮帮忙

使用 PHP 在运行 Windows Server 2012 的物理服务器上连接到 SQL Server 2012