Parallel ForEach调用外部服务时限制为两个核
Parallel ForEach is Limited to Two Cores When Calling Exteranl Service
我正在尝试遍历包含 20,000 多条客户记录的列表。我正在使用 Parallel.ForEach() 循环来尝试加快处理速度。在委托函数内,我正在向外部 Web 服务发送 HTTP POST 以验证客户信息。这样做时,循环被限制为 2 个线程或逻辑核心。如果我尝试增加并行度,进程会抛出错误 "The underlying connection was closed: A connection that was expected to be kept alive was closed by the server"
这是使用外部进程时循环的默认行为还是接收网络服务器的限制?
我的代码相当简单:
Parallel.ForEach ( customerlist, new ParallelOptions {MaxDegreeOfParallelism = 3 },( currentCustomer ) =>
{
if ( IsNotACustomer ( currentCustomer.TIN ) == true ) <--IsNotCustomer is where the HTTP POST takes place
{
...Write data to flat file...
}
});
如果我将 MaxDegreesOfParallelism 更改为 2,循环 运行 没问题。
此代码大约需要 80 分钟才能完成 20,000 条记录。虽然这并非不可接受,但如果我可以通过增加线程数来缩短该时间,那就更好了。
完整的异常消息(没有堆栈跟踪):
System.Net.WebException: The underlying connection was closed: A
connection that was expected to be kept alive was closed by the
server.
at System.Net.HttpWebRequest.GetResponse()
如有任何帮助,我们将不胜感激。
EDIT
HTTP POST 代码是:
HttpWebRequest request = ( HttpWebRequest )WebRequest.Create ( AppConfig.ESLBridgeURL + action );
request.Method = "POST";
request.GetRequestStream ( ).Write ( Encoding.UTF8.GetBytes ( body ), 0, body.Length );
Stream stream = request.GetResponse ( ).GetResponseStream ( );
StreamReader reader = new StreamReader ( stream );
output = reader.ReadToEnd ( );
URL 用于内部服务器 运行ning 专有 Web Sphere MQ 服务。其要点是检查内部数据源,看看我们是否与客户有关系。
我们 运行 我们每天在数百个站点的客户关系管理流程中采用相同的流程。所以我不认为存在任何许可问题,而且我确信这些 MQ 服务可以接受每个客户端的多个调用。
EDIT 2
更多的研究表明 2 个连接限制是有效的。但是,使用 ServicePointManager 可能能够绕过此限制。我找不到的是将 ServicePointManager 与 HttpWebRequests 结合使用的 C# 示例。
任何人都可以指出有效资源或提供代码示例吗?
您可能 运行 超出了默认的 2 个客户端限制。参见 System.Net.ServicePointManager.DefaultConnectionLimit
on MSDN。
The maximum number of concurrent connections allowed by a ServicePoint object. The default value is 2.
可能相关的问题:How Can I programmatically remove the 2 connection limit in WebClient?
感谢马特·斯蒂芬森和马特·乔丹为我指明了正确的方向。
我找到了一个将我的处理量减半的解决方案。我将继续调整以获得最佳结果,但这是我的结果。
我在应用程序配置文件中添加了以下内容:
<system.net>
<connectionManagement>
<add address="*" maxconnection="100"/>
</connectionManagement>
</system.net>
然后我想出了如何使用 ServicePointManager 并设置以下内容:
int dop = Environment.ProcessorCount;
ServicePointManager.MaxServicePoints = 4;
ServicePointManager.MaxServicePointIdleTime = 10000;
ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = dop * 10;
ServicePoint sp = ServicePointManager.FindServicePoint ( new Uri ( AppConfig.ESLBridgeURL ) );
对于我的开发机器,处理器数量是 8。
按原样,此代码使我能够在大约 45 分钟内处理我的 20,000 多条记录。
我正在尝试遍历包含 20,000 多条客户记录的列表。我正在使用 Parallel.ForEach() 循环来尝试加快处理速度。在委托函数内,我正在向外部 Web 服务发送 HTTP POST 以验证客户信息。这样做时,循环被限制为 2 个线程或逻辑核心。如果我尝试增加并行度,进程会抛出错误 "The underlying connection was closed: A connection that was expected to be kept alive was closed by the server"
这是使用外部进程时循环的默认行为还是接收网络服务器的限制?
我的代码相当简单:
Parallel.ForEach ( customerlist, new ParallelOptions {MaxDegreeOfParallelism = 3 },( currentCustomer ) =>
{
if ( IsNotACustomer ( currentCustomer.TIN ) == true ) <--IsNotCustomer is where the HTTP POST takes place
{
...Write data to flat file...
}
});
如果我将 MaxDegreesOfParallelism 更改为 2,循环 运行 没问题。
此代码大约需要 80 分钟才能完成 20,000 条记录。虽然这并非不可接受,但如果我可以通过增加线程数来缩短该时间,那就更好了。
完整的异常消息(没有堆栈跟踪):
System.Net.WebException: The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
at System.Net.HttpWebRequest.GetResponse()
如有任何帮助,我们将不胜感激。
EDIT
HTTP POST 代码是:
HttpWebRequest request = ( HttpWebRequest )WebRequest.Create ( AppConfig.ESLBridgeURL + action );
request.Method = "POST";
request.GetRequestStream ( ).Write ( Encoding.UTF8.GetBytes ( body ), 0, body.Length );
Stream stream = request.GetResponse ( ).GetResponseStream ( );
StreamReader reader = new StreamReader ( stream );
output = reader.ReadToEnd ( );
URL 用于内部服务器 运行ning 专有 Web Sphere MQ 服务。其要点是检查内部数据源,看看我们是否与客户有关系。
我们 运行 我们每天在数百个站点的客户关系管理流程中采用相同的流程。所以我不认为存在任何许可问题,而且我确信这些 MQ 服务可以接受每个客户端的多个调用。
EDIT 2
更多的研究表明 2 个连接限制是有效的。但是,使用 ServicePointManager 可能能够绕过此限制。我找不到的是将 ServicePointManager 与 HttpWebRequests 结合使用的 C# 示例。
任何人都可以指出有效资源或提供代码示例吗?
您可能 运行 超出了默认的 2 个客户端限制。参见 System.Net.ServicePointManager.DefaultConnectionLimit
on MSDN。
The maximum number of concurrent connections allowed by a ServicePoint object. The default value is 2.
可能相关的问题:How Can I programmatically remove the 2 connection limit in WebClient?
感谢马特·斯蒂芬森和马特·乔丹为我指明了正确的方向。
我找到了一个将我的处理量减半的解决方案。我将继续调整以获得最佳结果,但这是我的结果。
我在应用程序配置文件中添加了以下内容:
<system.net>
<connectionManagement>
<add address="*" maxconnection="100"/>
</connectionManagement>
</system.net>
然后我想出了如何使用 ServicePointManager 并设置以下内容:
int dop = Environment.ProcessorCount;
ServicePointManager.MaxServicePoints = 4;
ServicePointManager.MaxServicePointIdleTime = 10000;
ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = dop * 10;
ServicePoint sp = ServicePointManager.FindServicePoint ( new Uri ( AppConfig.ESLBridgeURL ) );
对于我的开发机器,处理器数量是 8。
按原样,此代码使我能够在大约 45 分钟内处理我的 20,000 多条记录。