【问题标题】:Multiple concurrent threads with web queries issue具有 Web 查询问题的多个并发线程
【发布时间】:2018-09-12 16:09:17
【问题描述】:

我正在构建相当复杂的并发系统并偶然发现了奇怪的问题。我会尽量简单。

  1. 我在 .net core 2.1 上有一个单实例控制台应用程序
  2. 我有一个 HttpClient 实例
  3. 我设置了以下参数: System.Net.ServicePointManager.DefaultConnectionLimit = int.MaxValue; System.Net.ServicePointManager.ReusePort = true; HttpClient.DefaultRequestHeaders.ConnectionClose = true; HttpClient.SetBearerToken(SOME_TOKEN);
  4. 我有一个线程 (A),它使用 ThreadPool/new Thread() 不断创建多达 30 个新的并发线程,并在内部使用单个 HTTP GET 查询(两者都试过了) 并将结果放入 ConcurrentQueue 变量中。
  5. 我有另一个线程 (B) 从队列中读取数据并不断创建多达 30 个新的并发线程,其中包含一个 HTTP POST 查询。

问题是我得到以下工作流程:

  1. A 线程运行良好,向队列提供结果。所有线程都运行良好。
  2. 在 A 线程启动之后,B 线程开始为 POST 创建子线程。
  3. A 线程完成了它的工作,所有线程都完成了。此时B线程创建的所有线程都挂在await client.PostAsync()方法上。
  4. 应用挂起大约 10 秒。
  5. VS 日志显示多个线程 0x35e0 已退出,代码为 0 (0x0)。 假定先前使用的线程正在释放的消息。为什么这么久?!
  6. 应用程序额外挂起 20 秒
  7. B 线程创建的第一个线程开始失败,然后所有其他 B 线程开始正常执行。

试过了:

  1. 一次将并发线程数减少到 5-10 可以解决问题,但会完全破坏并发性能。

  2. 我在日志中看到线程数并且没有溢出,A 和 B 一次最多 30 个线程(最多大约 60 个)

  3. 已尝试降低 System.Net.ServicePointManager.DefaultConnectionLimit 参数,但无济于事。

看起来有什么东西阻止了 POST 查询,然后他们又正常地冲了过来。请就这个问题提出建议。谢谢。

PS:我使用 Flickr 查询。会不会是他们的一些访问限制?无论如何,POST 挂起看起来很奇怪,它只是挂起而没有一次进入通行证。

【问题讨论】:

  • 所以你可能有多达 60 多个线程?这听起来太多了,我希望这些线程之间的所有上下文切换都会影响性能。最好只使用 5 到 10 个线程,并了解和修复使用该线程数的缓慢性能。越多线程不一定越好!
  • 可能是我对现代 PC 可以处理多少线程过于乐观,但 5-10 对我来说似乎是一个很低的数字。我希望我能得到更多,正如我所说的,它适用于 GET 查询线程。
  • 现代 PC 可以处理大量线程,但不一定高效。您的 CPU 只能在物理上运行几个并发执行(取决于内核数量、共享资源的争用等);添加更多线程只会使性能变差,因为 CPU 必须在它们之间进行上下文切换,并且会增加资源争用。例如,B 线程长时间等待的设计对我来说似乎是可疑的——这些线程处于空闲状态,可能正在做其他有用的工作。

标签: c# .net multithreading concurrency .net-core


【解决方案1】:

感谢Polyfun,将应用程序限制为更少的持续运行线程而不是无休止地创建数百个线程是一个好主意。

虽然速度变慢的真正原因是查询期间的一些可支配资源没有被释放时资源阻塞。包括由客户管理的较低级别代码保留的 HttpWebResponse 实体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2014-11-02
    • 1970-01-01
    • 2011-03-07
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多