Linq AsParallel()可以过早地处理SoapHttpClientProtocol对象吗?

时间:2014-10-10 20:14:10

标签: c# asp.net-mvc-4 soap-client plinq arcgis-server

在我正在研究的ASP.Net MVC 4 Web应用程序中。我有一个页面,它基本上通过从SOAP服务获取数据生成报告。

我的代码基本上看起来像这样

List<CustomThings> serverInfos = ServerInfos;
serverInfos.AsParallel().ForAll(srvInfo =>
{
    SoapHttpClientProtocol soapProxy = CreateProxy(srvInfo);
    //call make soap calls through the soap client
    //store results in the proper places
}

我在这里做AsParallel的原因是因为以串行方式通过HTTP执行多个请求需要永远。我应该投入 此代码确实有效,但偶尔会

是否有可能以不可预测的方式处理事情,PLINQ不是我在这里尝试做的好解决方案?

是否有可能另一个线程问题可能导致错误,导致soap客户端“放弃”?

其他信息

此特定肥皂代理与ArcGIS Server通信。通常,您可以检查服务器日志,查看启动特定请求的时间以及请求是否失败。这些日志中没有显示任何内容。


这是我从AsParallel代码获得的内部异常堆栈跟踪的示例。

  

异常:System.AggregateException:发生了一个或多个错误。   ---&GT; System.Net.WebException:基础连接已关闭:预期保持活动状态的连接已被关闭   服务器。 ---&GT; System.IO.IOException:无法从中读取数据   传输连接:强制关闭现有连接   远程主机。 ---&GT; System.Net.Sockets.SocketException:现有的   连接被远程主机强行关闭   System.Net.Sockets.Socket.Receive(Byte []缓冲区,Int32偏移量,Int32   size,SocketFlags socketFlags)at   System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,   Int32 size)---内部异常堆栈跟踪结束--- at   System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,   在System.Net.PooledStream.Read(Byte []缓冲区,Int32中的Int32大小)   offset,Int32 size)at   System.Net.Connection.SyncRead(HttpWebRequest请求,布尔值   userRetrievedStream,Boolean probeRead)---内部异常结束   堆栈跟踪--- at   System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest的   请求)   System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest的   请求)   System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(字符串   methodName,Object [] parameters)at   ESRI.ArcGIS.SOAP.FeatureServerProxy.Query(Int32 LayerOrTableID,String   DefinitionExpression,QueryFilter QueryFilter,ServiceDataOptions   ServiceDataOptions,String GdbVersion,Double MaximumAllowableOffset)   在   System.Linq.Parallel.SelectQueryOperator 2.SelectQueryOperatorResults.GetElement(Int32 index) at System.Linq.Parallel.QueryResults 1.get_Item(Int32 index)   在   System.Linq.Parallel.PartitionedDataSource 1.ListContiguousIndexRangeEnumerator.MoveNext(T& currentElement, Int32& currentKey) at System.Linq.Parallel.PipelineSpoolingTask 2.SpoolingWork()at   System.Linq.Parallel.SpoolingTaskBase.Work()at   System.Linq.Parallel.QueryTask.BaseWork(Object unused)at   System.Linq.Parallel.QueryTask。&lt; .cctor&gt; b__0(Object o)at at   System.Threading.Tasks.Task.InnerInvoke()at   System.Threading.Tasks.Task.Execute()

2 个答案:

答案 0 :(得分:2)

PLINQ甚至不知道您的连接对象存在。它无法关闭它。

仔细阅读信息:

  

远程主机强行关闭现有连接。

服务器以意外方式关闭了连接。你的客户没有错。

准确地解释异常是一项必不可少的调试技巧。此信息就在异常消息中。

也许你产生了太多的负担。设定可持续的并行度。默认的启发式方法是CPU工作,而不是IO。

.WithDegreeOfParallelism(10)
  

服务器已关闭预期保持活动状态的连接。

这可能意味着服务器不支持HTTP保持活动状态。

答案 1 :(得分:1)

我认为你的Soap HTTP请求AsParallel没有做任何可怕的错误,我不认为这是一个线程问题。

但是,并行请求显然会将您的客户端/服务器推送到连接限制的数量,这就是您看到连接关闭的原因。

我敢打赌,您的客户端,服务器或两者都没有配置为处理您发出的并发连接数。这就是为什么它以串行方式运行请求时的效果。

我猜您无法访问服务器配置,因此您可以做的一件事就是通过设置ParallelEnumerable.WithDegreeOfParallelism设置来同时控制您向服务器发出的并行请求数量以下代码段:

.AsParallel()
.WithDegreeOfParallelism(15)

这样就可以控制并行性,并且不会因为少量连接上的大量请求而使服务器过载。

关于客户端,您应确保已设置最大值。并发客户端连接到适当数量的数量,只是为了确保您的请求可以使用与服务器的单独连接,并防止重用可能导致Keep-Alive问题的连接。 如果使用连接的请求数超过了保持活动最大连接数或超过了超时设置,服务器可以关闭连接

您可以使用ServicePointManager.DefaultConnectionLimit设置以编程方式设置客户端连接限制。例如。你可以把它设置为50:

System.Net.ServicePointManager.DefaultConnectionLimit = 50;

以下是设置最大值的示例。使用配置文件连接到50:

<configuration> 
 <system.net> 
   <connectionManagement> 
     <add address="*" maxconnection="50" /> 
   </connectionManagement> 
 </system.net> 

我只使用“50”作为示例,您应该确定/计算/衡量设置的最佳设置。

还要确保在每次请求后正确处理HTTP连接以防止连接超时。