【发布时间】:2015-10-02 01:17:19
【问题描述】:
我有一个 Windows 服务,其代码类似于以下内容:
List<Buyer>() buyers = GetBuyers();
var results = new List<Result();
Parallel.Foreach(buyers, buyer =>
{
// do some prep work, log some data, etc.
// call out to an external service that can take up to 15 seconds each to return
results.Add(Bid(buyer));
}
// Parallel foreach must have completed by the time this code executes
foreach (var result in results)
{
// do some work
}
这一切都很好,而且很有效,但我认为我们遇到了可扩展性问题。我们平均每分钟有 20-30 个入站连接,每个连接都会触发此代码。每个入站连接的“买家”集合中可以包含 1-15 个买家。有时,我们的入站连接数会飙升至每分钟 100 多个连接,并且我们的服务器会停止运行。
每台服务器上的 CPU 使用率只有 50% 左右(两台负载平衡的 8 核服务器),但线程数继续增加(进程中的线程数达到 350 个),我们对每个入站连接的响应时间从 3- 4 秒到 1.5-2 分钟。
我怀疑上面的代码是造成我们的可伸缩性问题的原因。鉴于 Windows 服务(无 UI)上的这种使用场景(I/O 操作的并行性),Parallel.ForEach 是最好的方法吗?我在异步编程方面没有太多经验,我期待利用这个机会了解更多关于它的信息,我想我会从这里开始获得一些社区建议,以补充我在 Google 上找到的内容。
【问题讨论】:
-
平均而言,在任何给定时刻有多少请求被执行?
-
这看起来不太适合使用
Parallel.For,因为大多数线程会阻塞,从而导致线程池产生新线程。对于 IO,请改用异步。 -
将减少 MaxDegreeOfParallelism 帮助
Parallel.ForEach(list, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount, }, parallelAction);