5

我正在开发一项新服务来为我们公司的多个 Web 资产运行 QA,并且遇到了一个有趣的网络并发问题。为了提高性能,我使用 TPL 根据大量 url 创建 HttpWebRequest,以便它们可以并行运行;但是,我似乎无法找到过程中的瓶颈所在。

到目前为止我的观察:

  • 我最多可以通过 TPL 获得大约 25-30 个并行线程
  • 服务的 CPU 永远不会中断 5-6%(在 1 - 4 个内核上运行,有和没有 H/T)
  • NIC 使用率从不中断 2-3%
  • 整体网络流量似乎没有受到影响(其他用户没有抱怨,同时运行的速度测试没有显示出太大的影响)
  • 在我们的办公网络 (15Mbps) 或我们的数据中心 (100+Mbps) 上运行之间的速度变化不大
  • 通过一次从多台主机下载而不是从一台主机下载大量页面,我获得了一点性能提升。

可能的痛点:

  • CPU(内核或硬件线程数)
  • 网卡
  • 最大允许并发 HttpWebRequest 数
  • 局域网
  • 广域网
  • 路由器/交换机/负载均衡器

所以问题是:

显然,现在可以在几分钟内下载整个互联网,但我很想知道在这种情况下瓶颈在哪里,以及可以采取什么措施来克服它。

附带说明一下,我们目前正在使用 3rd 方服务进行抓取,但我们在某些方面受到它们的限制,并且希望获得更大的灵活性。关于公司秘密酱汁或箭尖上的毒药...... :)

4

3 回答 3

7

我强烈怀疑以下原因之一是:

  1. 您遇到了默认连接限制。检查 ServicePointManager.DefaultConnectionLimit 的值。我建议您将其设置为几乎无限的值,例如 1000。
  2. TPL 没有启动足够多的线程来使网络饱和。请注意,远程 Web 服务器可能有大量延迟。在等待期间,您的线程不会对网络施加负载。

TPL 不保证任何最低并行度 (DOP)。这很可惜,因为有时在使用 IO 时,您确实需要准确控制并行度。

我建议您手动启动固定数量的线程来执行 IO,因为这是保证特定 DOP 的唯一方法。您需要试验确切的值。它可能在 50 到 500 的范围内。您可以减少线程的默认堆栈大小,以节省那么多线程的内存。

于 2012-06-19T16:34:34.937 回答
1

也许你达到了 TCP 连接限制,或者没有正确处理连接,无论如何尝试使用 JMeter 之类的东西来查看你可以获得的最大并发 HTTP 吞吐量。

于 2012-06-19T16:37:50.307 回答
1

代码真的很简单。我使用 Parallel.ForEach 循环访问一组 URL(字符串)。该操作创建一个 HttpWebRequest,然后将结果转储到 ConcurrentBag。顺便说一句,NCrawler 似乎很有趣;我会检查一下。谢谢你的提示。

因为用 Parallel.ForEach 是不可能控制线程数的,所以我建议至少切换到一个ThreadPool.

您可以使用它QueueUserWorkItem来分配工作,直到您的任务集合完全推送到工作线程或直到方法返回 false(池中没有更多线程)。

ThreadPool您可以控制要分配的最大线程SetMaxThreads数。

于 2012-06-19T17:05:57.577 回答