如何优化对服务的并行调用?

How do I optimize parallel calls to a service?

我在需要从服务中提取数据时遇到了一个挑战。我正在对 Parallel.ForEach:

使用以下调用
Parallel.ForEach(idList, id => GetDetails(id));

GetDetails(id) 调用 Web 服务大约需要半秒钟,并将生成的详细信息添加到列表中。

static void GetDetails(string id)
{
    var details = WebService.GetDetails(Key, Secret, id);
    AllDetails.Add(id, details);
}

问题是,我知道该服务可以处理更多调用,但我似乎无法弄清楚如何让我的进程增加更多调用,UNLESS 我拆分我的列表并多次打开该过程。换句话说,如果我打开这个应用程序 GetDetails.exe 4 次并将 ID 的数量拆分为每个,我将 运行 的时间减少到原来的 25%。这告诉我存在这种可能性,但我不确定如何在不多次启动控制台应用程序的情况下实现它。

希望这对于更熟悉并行性的人来说是一个非常简单的问题,但在我的研究中,我还没有在没有 运行 多个实例的情况下解决它。

几种可能性:

  • 有可能 WebService.GetDetails(...) 正在使用某种机制来确保一次实际上只发生一个 Web 请求。
  • .NET 本身可能会限制给定主机或一般情况下的连接数 see this question's answers for details about these kinds of problems
  • 如果 WebService.GetDetails(...) 重复使用某种标识符,如会话密钥,服务器 可能会限制它为该会话接受的并发请求数。
  • 尝试通过向服务器发送更多并发请求来解决性能问题通常不是一个好主意。如果您控制服务器,那么您将导致您自己的服务器做比它需要做的更多的工作。如果不是,您 运行 有被 IP 禁止或滥用其服务的风险。值得检查一下您正在访问的服务是否有一些选项来批处理您的请求或其他东西。
  • 正如 Scott Chamberlain 在评论中提到的那样,您需要小心处理并行进程,因为从多个线程同时访问 Dictionary<> 等结构可能会导致零星的、难以追踪的错误。您最好使用 async 请求而不是并行线程。如果您小心 await,您可以同时激活多个请求,同时仍一次只使用一个线程。