数据的异步处理

在那一刻我试图组装一个异步tcp服务器来接收我想要处理的数据,提取值并插入到sql server。

我认为最好的基本概念是一旦数据被接收并确认为整个消息,那么消息应该被传递到某种集合以等待基于FIFO的处理,这将解析值并将它们插入到sql server。 我想这就是消费者/生产者模式。

我一直在寻找最好的收集/方式来做到这一点,到目前为止看到BlockingCollection,ConcurrentCollection和BufferBlock使用async / await,我认为这可能是要走的路,但说实话我不确定。

我找到的最好的例子是Stephen Cleary的博客,特别是这篇文章, http://blog.stephencleary.com/2012/11/async-producerconsumer-queue-using.html

我的主要保留意见是,我绝不想放慢速度或中断接收消息,我建议使用多个生产者/消费者示例,这可以在上面的链接中看到,但我想知道的是;

  • 我在这个假设中是正确的,还是在我的场景中有更合适的方法。
  • 如果我在我的假设中是正确的,那么考虑到我的用例,任何人都可以建议实现这一点的最佳方法。

任何和所有的帮助非常感谢。

在那一刻我试图组装一个异步tcp服务器来接收我想要处理的数据,提取值并插入到sql server。

这种情况有一个常见的陷阱。 当工作尚未完成时,将成功报告给客户通常是错误的。 大部分时间我都看过这种设计,这是因为开发人员自己施加的效率“要求”,而不是客户或技术原因。 首先,退一步, 确保您确实希望在操作尚未实际完成时向客户端返回“成功完成”消息。

如果您确定这是您想要做的事情,那么您还必须提出另一个问题:丢失请求是否可以接受? 也就是说,在告诉客户端操作成功完成后,如果操作实际上没有完成,系统是否仍然稳定?

这个问题的答案通常是“不”。 此时,最常见的体系结构解决方案是拥有一个进程外可靠队列(例如Azure队列或MSMQ),以及处理队列消息的独立后端(例如Azure工作者角色或Win32服务) 。 这肯定使架构复杂化,但如果系统必须尽早返回完成消息并且不得丢失消息,则这是必要的复杂性。

另一方面,如果丢失消息是可以接受的,那么您可以将它们保留在内存中。 只有在这种情况下,您才能使用我博客中提到的内存生产者/消费者类型之一。 这是一种非常罕见的情况,但确实会不时发生。

一般来说,我会避免使用BlockingCollection和朋友进行这类工作。 这样做可以鼓励您将整个系统架构到一个流程中,这是可扩展性和可靠性的敌人。

我第二个Stephen Cleary建议使用进程外队列来管理工作。 我不同意这必然使架构复杂化 – 事实上,我认为它可以使事情变得更加简单。 具体而言,原始需求的主要复杂性(“将异步tcp服务器放在一起”)消失了。 异步TCP服务器是一个痛苦的写入和易于搞砸 – 为什么不完全跳过该部分,并可以自由地将所有精力集中在后处理代码上?

当我构建这样的系统时,我使用Redis List作为任务队列。 任务被序列化为JSON,客户端将使用RPUSH命令将其任务添加到队列中。 工作进程从队列BLPOP中检索下一个任务,做他们的事情,然后返回等待下一个任务。

好处:

  • 没有锁。 所有同步都是免费的Redis(或您选择的任何任务队列)。
  • 系统中的所有东西都是单线程的。 multithreading很难
  • 我可以根据需要自由调整尽可能多的工作进程。