WCF: 套接字连接中止。远程主机超过了接收超时。

3
我一直在处理WCF的一个难题。我有一个WCF服务(作为Windows服务托管),由控制台应用程序调用。它工作得很好,但最近我们遇到了一个超时问题,当我们需要针对遗留系统运行查询时会出现10分钟的超时。

我在服务和客户端.exe中都使用log4net,奇怪的是,服务实际上完成了任务并没有抛出异常。它运行了查询(大约需要12分钟),创建了一个文件,并记录下成功日志。

然而,控制台应用程序日志中记录了一个异常,声称“主机”返回了一个超时或错误。我认为这是一个超时而不是缓冲区问题,因为异常总是在初始呼叫后的10分钟精确到秒时发生。

以下是来自我的log4net的异常/堆栈信息:

2015-07-28 17:35:47,364 [1] 
System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.9843999'. ---> System.IO.IOException: The read operation failed, see inner exception. ---> System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.9843999'. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
   --- End of inner exception stack trace ---
   at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
   at System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   at System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   at System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security.NegotiateStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   --- End of inner exception stack trace ---
   at System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.NegotiateStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   at System.ServiceModel.Channels.SessionConnectionReader.Receive(TimeSpan timeout)
   at System.ServiceModel.Channels.SynchronizedMessageSource.Receive(TimeSpan timeout)
   at System.ServiceModel.Channels.TransportDuplexSessionChannel.Receive(TimeSpan timeout)
   at System.ServiceModel.Channels.TransportDuplexSessionChannel.TryReceive(TimeSpan timeout, Message& message)
   at System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at FileGeneratorConsole.FileGeneratorServiceReference.IFileGeneratorService.GenerateXmlFileFromSql(String sqlServer, String sqlDatabase, String sqlQuery, Int32 commandTimeout, Boolean allowEmptyResult, String outputFileName, String xslFileName, Boolean archiveExistingFile)
   at FileGeneratorConsole.Program.Main(String[] args)

现在,我认为我已经做了调查,并想出了问题可能是什么。我假设这是绑定定义的sendTimeout和receiveTimeout的问题,因此我已经添加了它们:

<bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_IFileGeneratorService"
                  maxBufferPoolSize="2147483647"
                 maxBufferSize="2147483647"
                 maxReceivedMessageSize="2147483647"
                 receiveTimeout="00:30:00"
                 closeTimeout="00:30:00"
                 openTimeout="00:30:00"
                 sendTimeout="00:30:00">
        </binding>
      </netTcpBinding>
    </bindings>

另外,如果您注意到上面的异常,您会发现错误信息说:

本地套接字超时为'00:29:59.9843999'

它以前是00:09:59... 所以看起来它已经生效了。

我还在服务配置文件中添加了这个,以防绑定需要在两侧使用,但这并没有帮助。

最后,出于绝望,我尝试添加了一些其他东西。我尝试在服务部分添加超时时间:

我还尝试添加

到行为本身。

现在我无法找到解决方法,它总是在10分钟后停止。

提前感谢您的帮助。


既然我在这里,不妨问一下。我已经在控制台中编写了代码,以输出绑定名称和超时属性,以确保它们在代理客户端中设置正确,看起来很好。但我不知道如何从服务代码本身调试相同的项目,以查看服务认为自己的超时设置是什么。谢谢。 - enforge
1个回答

6

事情总比你想象的简单。

可悲的是,一直缺少在服务端点中的bindingConfiguration引用。这段时间,服务一直在假定使用默认绑定定义运行。我在我的配置文件中定义了一个绑定,但错过了指定的部分:

我原本写成:

 <endpoint address="" binding="netTcpBinding" bindingConfiguration="">

我需要:

 <endpoint address="" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IFileGeneratorService">

一旦这个被设置好,我的实际服务端点就会查看正确的绑定属性。


4
WCF的配置确实非常棘手! - Jacob Rutherford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接