简体   繁体   English

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

[英]Queuing in OneWay WCF Messages using Windows Service and SQL Server

I need to implement a queuing mechanism for WCF service requests. 我需要为WCF服务请求实现一个排队机制。 The service will be called by clients in a one-way manner. 客户将以单向方式调用该服务。 These request messages should be stored in a SQL Server database and a Windows Service queues the messages. 这些请求消息应存储在SQL Server数据库中,Windows服务将对消息进行排队。 The time at which the requests are processed will be configurable. 处理请求的时间是可配置的。 If there happens error in processing the message, it need to be retried up to 100 times and if still fails it need to be terminated. 如果在处理消息时发生错误,则需要重试最多100次,如果仍然失败则需要终止。

Also there should be a mechanism to monitor the number of transaction made on a day and number of failures. 还应该有一种机制来监控一天的交易次数和失败次数。

QUESTIONS 质询

  1. If I were using MSMQ, clients could have forwarded the message to queue without knowing the service endpoint. 如果我使用MSMQ,客户端可能已将消息转发到队列而不知道服务端点。 But I am using SQL Server to store the request messages. 但我使用SQL Server来存储请求消息。 How the clients can put the requests to SQL Server? 客户端如何将请求发送到SQL Server?

  2. Is the solution feasible? 解决方案可行吗? Do we have any article/book that explains how to implement the above? 我们是否有任何文章/书籍解释如何实施上述内容?

  3. What are the steps to prevent service and client reaching faulted state in this scenario? 在这种情况下,防止服务和客户端到达故障状态的步骤是什么?

  4. What is the best method to store incoming message to database? 将传入消息存储到数据库的最佳方法是什么?

  5. What is the best method to implement retry mechanism? 实现重试机制的最佳方法是什么? Anything already exist so that I don't have to reinvent the wheel? 有什么东西已经存在,所以我不必重新发明轮子?

  6. Is there any book/article that explains this implementation? 是否有任何书/文章解释了这种实现?


NOTES 笔记

  1. Content of the message will be complex XML. 消息的内容将是复杂的XML。 For example Travel expense items of an employee or a list of employees. 例如,员工的旅行费用项目或员工列表。

READING

  1. Logging WCF Request to Database 将WCF请求记录到数据库

  2. Guaranteed processing of data in WCF service 保证WCF服务中的数据处理

  3. MSMQ vs. SQL Server Service Broker MSMQ与SQL Server Service Broker

  4. Is it possible to persist and then forward WCF messages to destination services? 是否可以保留然后将WCF消息转发到目标服务?

  5. WCF 4 Routing Service - protocol bridging issue WCF 4路由服务 - 协议桥接问题

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

  7. Integrating SQL Service Broker and NServiceBus 集成SQL Service Broker和NServiceBus

  8. Can a subscriber also publish/send message in NServiceBus? 订户是否也可以在NServiceBus中发布/发送消息?

I'm a DBA, so that flavors my my response, but here's what I'd do: 我是一名DBA,所以我的回答有点味道,但这就是我要做的事情:

  1. If you're using SQL 2005+, use Service Broker to store the messages in the database rather than storing them in a table. 如果您使用的是SQL 2005+,请使用Service Broker将消息存储在数据库中,而不是将它们存储在表中。 You get a queueing mechanism with this, so you can get rid of MSMQ. 你得到了一个排队机制,所以你可以摆脱MSMQ。 You'll also have a table, but it's just going to store the conversation handle (essentially, a pointer to the message) along with how many times it attempted this message. 您还将拥有一个表,但它只是存储会话句柄(本质上是指向消息的指针)以及它尝试此消息的次数。 Lastly, you'll want some sort of a "dead letter box" where messages that reach your retry threshold go. 最后,您需要某种“死信箱”,其中达到您的重试阈值的消息会消失。
  2. In your message processing code, do the following: 在邮件处理代码中,执行以下操作:
    • Begin a transaction 开始交易
    • Receive a message off of the queue 从队列中接收消息
    • If the retry count is greater than the threshold, move it to the dead letter box and commit 如果重试计数大于阈值,请将其移至死信框并提交
    • Increment the counter on the table for this message 增加此消息的表格上的计数器
    • Process the message 处理消息
    • If the processing succeeded, commit the transaction 如果处理成功,则提交事务
    • If the processing failed, put a new message on the queue with the same contents and then commit the transaction 如果处理失败,则在具有相同内容的队列上放置新消息,然后提交事务

Notice that there aren't any planned rollbacks. 请注意,没有任何计划的回滚。 Rollbacks in Service Broker can be bad; Service Broker中的回滚可能很糟糕; if you rollback 5 times without a successful receive, the queue will become disabled for both enqueuing and dequeuing. 如果在没有成功接收的情况下回滚5次,则队列将因排队和出列而被禁用。 But you still want to have transactions for the case when your message processor dies in the middle of processing (ie the server crashes). 但是当您的消息处理器在处理过程中死亡(即服务器崩溃)时,您仍然希望获得事务处理。

1. If I were using MSMQ, clients could have forwarded the message to queue without knowing the service endpoint. 1.如果我使用MSMQ,客户端可能已将消息转发到队列而不知道服务端点。

Yes - but they would need to know the MSMQ endpoint in order to send their message to the queue..... 是的 - 但是他们需要知道MSMQ端点才能将消息发送到队列.....

But I am using SQL Server to store the request messages. 但我使用SQL Server来存储请求消息。 How the clients can put the requests to SQL Server? 客户端如何将请求发送到SQL Server?

The clients won't put their requests into SQL Server - that's what the service on the server will do. 该客户端将不会把他们的请求到SQL Server -这就是在服务器上的服务就行了。 The client just call a service method, and the code in there will store the request into the SQL Server table. 客户端只调用一个服务方法,其中的代码将请求存储到SQL Server表中。

2. Is the solution feasible? 2.解决方案是否可行? Do we have any article/book that explains how to implement the above? 我们是否有任何文章/书籍解释如何实施上述内容?

Sure, I don't see any big issue. 当然,我没有看到任何大问题。 The only point unclear to me right now is: how will the clients know their results?? 我现在唯一不清楚的一点是:客户如何知道他们的结果? Do they need to go get results from another service or something?? 他们需要从其他服务或其他东西获得结果吗?

3. What are the steps to prevent service and client reaching faulted state in this scenario? 3.在这种情况下,防止服务和客户端到达故障状态的步骤是什么?

As always - just make sure your service code catches all exceptions and either handles them internally, or returns interoperable SOAP faults instead of .NET exceptions. 一如既往 - 只需确保您的服务代码捕获所有异常并在内部处理它们,或者返回可互操作的SOAP错误而不是.NET异常。

It sounds like what you want to do is similar to this: 这听起来像你想要做的是这样的:

在此输入图像描述

In this case you can use netMsmqBinding between your service and your service consumers. 在这种情况下,您可以在服务和服务使用者之间使用netMsmqBinding。

The only thing you won't get out of the box is the retrying. 你唯一不会想到的就是重试。 However if you make the queue transactional then this functionality can be implemented in your service code. 但是,如果您将队列设置为事务性,则可以在服务代码中实现此功能。

If there is a failure in your dequeue operation the message will not be removed from the queue. 如果您的出队操作失败,则不会从队列中删除该消息。 It will therefore be available for further dequeue attempts. 因此,它可用于进一步的出队尝试。

However, you would need to implement retry attempt threshold code which fails a message after a certain number of attempts. 但是,您需要实现重试尝试阈值代码,该代码在一定次数的尝试后失败。

I would suggest a different approach to the ones suggested here. 我建议采用与此处建议的方法不同的方法。 If you are able to, I would consider the introduction of a messaging framework such as NServiceBus . 如果你能够,我会考虑引入一个消息传递框架,如NServiceBus It satifies many of the requirements that you have right out of the box. 它满足了您开箱即用的许多要求。 Let me try and address this in context of your requirements. 让我尝试在您的要求的背景下解决这个问题。

The service will be called by clients in a one-way manner. 客户将以单向方式调用该服务。

All communication between endpoints in NServiceBus is one way. NServiceBus中端点之间的所有通信都是一种方式。 The underlying transport NServiceBus uses is MSMQ, so much like your WCF approach, your client is communicating with queues, rather than specific service endpoints. NServiceBus使用的底层传输是MSMQ,与您的WCF方法非常相似,您的客户端正在与队列进行通信,而不是特定的服务端点。

These request messages should be stored in a SQL Server database and a Windows Service queues the messages. 这些请求消息应存储在SQL Server数据库中,Windows服务将对消息进行排队。

If you wanted to store your request messages in a database then you can configure NServiceBus to forward all messages sent to your request processing endpoint to another "audit" queue, which you can use to persist to the database. 如果要将请求消息存储在数据库中,则可以将NServiceBus配置为将发送到请求处理端点的所有消息转发到另一个“审计”队列,您可以使用该队列持久保存到数据库。 This has the added benefit of separating your application logic from your auditing implementation. 这具有将应用程序逻辑与审计实现分离的额外好处。

The time at which the requests are processed will be configurable. 处理请求的时间是可配置的。

NServiceBus allows you to defer when a mesage is sent. NServiceBus允许您在发送消息时推迟。 Normally a message is sent via the Send method of a Bus instance - Bus.Send(msg). 通常,通过Bus实例的Send方法发送消息 - Bus.Send(msg)。 You can use The Defer method to send the message some time in the future eg. 您可以使用Defer方法在将来的某个时间发送消息,例如。 Bus.Defer(DateTime.Now.AddDays(1), msg); Bus.Defer(DateTime.Now.AddDays(1),msg); There's nothing more you really have to do, NserviceBus will handle the message once the specified time has been reached. 您真的不需要做什么,NserviceBus将在达到指定时间后处理该消息。

If there happens error in processing the message, it need to be retried up to 100 times and if still fails it need to be terminated. 如果在处理消息时发生错误,则需要重试最多100次,如果仍然失败则需要终止。

By default, NServiceBus will enlist your message in a transaction as soon as your message leaves the queue. 默认情况下,NServiceBus将在您的消息离开队列后立即在事务中登记您的消息。 This ensures that in the event of failure that the message is rolled back to the originating queue. 这可确保在发生故障时将消息回滚到原始队列。 In such an event, NServiceBus will automatically try to reprocess the message a configurable number of times. 在这种情况下,NServiceBus将自动尝试重新处理消息可配置的次数。 The default being 5. You can of course set this to whatever you want, although I am not sure why you would want to set this to 100. At any rate, NServiceBus uses this setting to stop an endless loop of automatic retries. 默认为5.您当然可以将其设置为您想要的任何内容,但我不确定您为什么要将此设置为100.无论如何,NServiceBus使用此设置来停止无限循环的自动重试。 Once the limit has been reached the message is sent to an error queue where it sits until you fix whatever issues caused the exception or until you decide to push the message back to the queue for processing. 达到限制后,消息将发送到错误队列,直到您修复导致异常的任何问题或直到您决定将消息推回队列进行处理为止。 Either way, you are assured that the message is never lost. 无论哪种方式,您都可以确信该消息永远不会丢失。

Also there should be a mechanism to monitor the number of transaction made on a day and number of failures. 还应该有一种机制来监控一天的交易次数和失败次数。

The beauty of using MSMQ as the transport is that performance monitoring can be a achieved at a infrastructure level. 使用MSMQ作为传输的美妙之处在于,性能监控可以在基础架构级别实现。 How your applications perform, can be measured by how long they sit in the queue. 您的应用程序的执行方式可以通过它们在队列中的时间来衡量。 NServiceBus comes with performance monitors that track the length of time a message is in the queue and you can also add perf mons that come built into windows to track other activity. NServiceBus带有性能监视器,可跟踪消息在队列中的时间长度,还可以添加内置于窗口中的perf mon来跟踪其他活动。 To monitor errors, all you need to do is check the number of messages in the error queue. 要监视错误,您需要做的就是检查错误队列中的消息数。

One of the main features of NServiceBus is reliability. NServiceBus的主要功能之一是可靠性。 WCF will only do so much for you, and then you are on your own. WCF只会为你做这么多,然后你自己。 That's a lot of code, complexity and frankly hugely error prone. 这是很多代码,复杂性和坦率地说非常容易出错。 The things I have described here are all standard features of NServiceBus and I have barely scratched the surface with all the other things that you can do with it. 我在这里描述的东西都是NServiceBus的标准功能,我几乎没有用你可以用它做的所有其他事情。 I recommend you check it out. 我建议你看看。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM