【问题标题】:Asynchronous Processing of Data数据的异步处理
【发布时间】:2014-02-13 18:24:39
【问题描述】:

目前我正在尝试组建一个异步 tcp 服务器来接收我想要处理的数据,提取值并插入到 sql server。

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

我一直在研究最好的收集/方法,到目前为止,我已经看到了使用 async/await 的 BlockingCollection、ConcurrentCollection 和 BufferBlock,我认为这可能是要走的路,但老实说我不确定.

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

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

  • 我的假设是否正确,或者在我的场景中是否有更合适的方法。
  • 如果我的假设是正确的,那么考虑到我的用例,任何人都可以提出最佳的实现方式。

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

【问题讨论】:

    标签: c# .net collections task-parallel-library async-await


    【解决方案1】:

    目前我正在尝试组建一个异步 tcp 服务器来接收我想要处理的数据,提取值并插入到 sql server。

    这种情况有一个常见的陷阱。在工作尚未完成时向客户报告成功通常是错误的。大多数时候,我看到这种设计,是因为开发人员自己强加的效率“要求”,而不是客户或技术原因。因此,首先,退后一步,绝对确定您确实希望在操作尚未实际完成时向客户端返回“成功完成”消息。

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

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

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

    【讨论】:

    • 如果您不介意我询问在什么情况下请求会丢失或操作未完成。例如,如果抛出异常,会不会是这样?
    • 任何可能导致服务器意外关闭的情况。这可能是从电源线跳闸到安装 Microsoft 更新补丁后重新启动。服务器意外关闭的原因可以减轻但永远无法消除,因此必须编写软件来处理这种故障情况。
    • 啊,我明白了,如果有 10 x byte[] 等待处理并且服务器/应用程序由于某种原因被终止或断开连接,那些未处理的消息基本上会消失永远与进程外队列一样,您只需继续处理仍在队列中的任何项目,因为这些项目已提交到某个地方的存储。
    • @JohnyHarkness:没错。
    【解决方案2】:

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

    我第二 Stephen Cleary's suggestion 使用进程外队列来管理工作。我不同意这必然会使架构复杂化——事实上,我认为它可以让事情变得相当简单。具体来说,原始要求(“将异步 tcp 服务器放在一起”)的主要复杂性消失了。异步 TCP 服务器编写起来很麻烦,而且很容易搞砸 - 为什么不干脆跳过这部分,把所有精力都集中在后处理代码上?

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

    优点:

    • 没有锁。所有同步都来自 Redis(或您选择的任何任务队列)免费提供。
    • 系统中的一切都是单线程的。 多线程很难
    • 我可以在任意数量的节点上随意启动任意数量的工作进程。

    【讨论】:

    • 本例中的客户端是 gps 设备,因此我无法控制它们如何传输数据。唯一的选择是将它们指向一个 tcp 端口并读取传输的字节。是否可以使用消息队列执行此操作并让工作进程读取从队列传输的字节?
    • 对于 Redis,您需要一些轻量级的守护进程来接收来自 GPS 设备的消息并将它们转换为 RPUSH 命令。我很想知道是否有一个“无协议”的消息队列系统 - 只需获取原始 TCP 数据包并将它们放入可靠的队列中进行后处理。看起来它应该是可能的(并且有用!)
    猜你喜欢
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 2021-09-26
    • 1970-01-01
    • 2019-09-04
    • 2014-08-05
    相关资源
    最近更新 更多