【问题标题】:Azure - C# Concurrency - Best PracticesAzure - C# 并发 - 最佳实践
【发布时间】:2015-09-02 13:54:46
【问题描述】:

我们正在使用 Microsoft Azure 抓取基于 Web 的 API。问题是要检索的数据太多(涉及组合/排列)。

如果我们使用标准的 Web Job 方法,我们计算出大约需要 200 年的时间来处理我们想要获取的所有数据 - 我们希望我们的数据每周刷新一次。

来自 API 的每个请求/响应大约需要 0.5-1.0 秒来处理。请求大小平均为 20000 字节,平均响应为 35000 字节。我相信请求的总数是数百万。

另一种思考这个问题的方法是:如何使用 Azure 到 Web 抓取 - 并确保不会使运行它的 VM 过载(就内存 + 网络而言)? (我认为在这种情况下你不需要太多的 CPU 处理)。

到目前为止我们所做的尝试:

  1. 使用的 Service Bus Queues/Worker Roles 扩展到 8 个小型 VM - 但这会导致发生大量网络错误(每个工作角色 VM 可以处理的数量必须有一定的网络限制) .
  2. 使用的 Service Bus Queues/Continuous Web Job 扩展到 8 个小型 VM - 但这似乎工作得更慢 - 甚至扩展,并没有让我们对幕后发生的事情有太多控制。 (我们真的不知道有多少虚拟机启动了)。

这些东西似乎是为 CPU 计算而构建的,而不是为 Web/API 抓取而构建的。

澄清一下:我将我的请求放入一个队列中,然后我的多个 VM 会拾取该队列以进行处理以获取响应。这就是我使用队列的方式。每个 VM 都使用 Microsoft 规定的 ServiceBusTrigger 类。

  1. 小型 VM 多还是大型 VM 少?
  2. 我们应该查看哪些 C# 类?
  3. 尝试在 Azure 上执行此类操作时,有哪些技术最佳实践?

【问题讨论】:

  • 您将可扩展性与并行处理混淆了。队列和服务总线提高了可扩展性。并行处理由任务并行库、PLINQ 等处理。单个进程可以处理 很多 个并发 HTTP 请求,因为大多数时候它只是在等待响应。
  • 也许我没有正确解释 - 我将我的 requests 放入队列中 - 然后我的多个 VM 将其拾取以进行处理以获取响应。这就是我使用队列的方式。每个 VM 都按照 MS 的规定使用 TPL 来使用 ServiceBusTrigger

标签: c# azure concurrency parallel-processing


【解决方案1】:

实际上,我已经在 Azure 中启动并运行了一个网络爬虫,已经有一段时间了 :-)

AFAIK 没有“灵丹妙药”。在截止日期前抓取大量资源非常困难。

它是如何工作的(最重要的事情):

  • 我使用辅助角色和 C# 代码作为代码本身。
  • 对于调度,我使用队列存储。我将抓取任务放入队列中并设置了超时时间(例如“何时抓取”),然后让爬虫将它们拉下来。您可以在队列大小上设置触发器,以确保您在速度方面满足最后期限 - 我个人不需要它们。
  • SQL Azure 很慢,所以我不使用它。相反,我只使用表存储来存储刮掉的项目。请注意,更新数据可能非常复杂。
  • 不要使用过多的线程;相反,对所有网络流量使用异步 IO。
  • 此外,您可能还需要考虑额外的线程需要额外的内存(解析树可能会变得非常大) - 因此需要权衡取舍...我确实记得使用过一些线程,但实际上只是少数几个。李>

请注意,如果您现在使用线程化方法,这可能确实需要您重新设计和重新实现完整的网络抓取工具。但同样,有一些好处:

  • 表存储和队列存储很便宜。
  • 我目前使用单个 Extra Small VM 来抓取超过一千个网络资源。
  • 入站网络流量免费。
  • 因此,结果也很便宜;我敢肯定它比替代品少得多。

至于我使用的类......嗯,这是一个有点长的列表。我将 HttpWebRequest 用于异步 HTTP 请求和 Azure SDK——但其余的都是手工制作的(而不是开源的)。

P.S.:这不仅仅适用于 Azure;其中大部分也适用于本地抓取工具。

【讨论】:

    【解决方案2】:

    我有一些刮痧的经验,所以我会分享我的想法。

    1. 这些东西似乎是为 CPU 计算而构建的,而不是为 Web/API 抓取而构建的。

    它们是为动态缩放而构建的,因为您的任务并不是您真正需要的。

    1. 如何确保不会使 VM 过载?

    测量响应时间和错误率并调整代码以降低它们。

    1. 我认为在这种情况下您不需要过多的 CPU 处理。

    取决于每秒传入的数据量以及您正在使用它做什么。对快速传入的数据进行更复杂的解析(如果您决定在同一台机器上进行)将很快耗尽 CPU。

    1. 8台小虚拟机造成大量网络错误(一定有网络限制)

    VM 越小,它们获得的共享资源就越少。存在吞吐量限制,然后您的邻居与您共享实际硬件存在问题。通常,您的实例越小,遇到的麻烦就越多。

    1. 小型 VM 多还是大型 VM 少?

    根据我的经验,较小的虚拟机太残缺了。但是,您的里程可能会有所不同,这完全取决于特定任务及其解决方案的实施。真的,你必须在你的环境中衡量自己。

    1. 我们应该查看哪些 C# 类?
    2. 尝试在 Azure 上执行此类操作时,有哪些技术最佳实践?

    对于高吞吐量抓取,您应该关注基础架构。你在不同的 Azure 数据中心会有不同的延迟,在不同的 VM 大小下,网络延迟/持续吞吐量会有不同的体验,具体取决于谁与你共享硬件。最佳做法是尝试找到最适合您的方法 - 更改数据中心、VM 大小并进行其他试验。

    Azure 可能不是解决此问题的最佳方案(除非您正在大肆消费)。 8 个小型 VM 每月 450 美元。购买具有 256Gb RAM、40 个硬件线程和 500Mbps - 1Gbps(甚至高达数 Gbps 突发)的优质网络带宽的非托管专用服务器就足够了,而且没有延迟问题。

    根据您的预算,您将拥有一个您不能超载的专用服务器。您将有足够的 RAM 来处理异步固定(如果您决定采用异步方式),或者有足够的硬件线程用于多线程同步 IO,从而提供最佳吞吐量(如果您选择与固定大小的线程池同步) .

    顺便说一句,根据 API 的具体情况,您的主要问题可能是当您开始对 API 端点施加过大压力时,API 所有者会简单地限制您爬行。

    【讨论】:

    • 感谢您的意见 - 您是否曾使用 Azure 进行抓取或它为抓取提供的下划线架构?
    • 我接受了这个想法并尝试了它。但是,面对您所描述的相同问题,我并没有走得太远。就金钱和所需的工作量而言,它太慢了,太贵了。最后,与专用服务器相比,这太麻烦了,没有明显的好处。我不需要动态扩展,结果证明专用硬件和适当的基础架构胜过一切。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 2015-03-14
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多