gpt4 book ai didi

wcf - 什么 130 秒超时正在杀死我的 WCF 流服务调用?

转载 作者:行者123 更新时间:2023-12-03 01:21:42 24 4
gpt4 key购买 nike

就在最近,我开始研究 WCF 流的一个棘手问题,如果客户端在两次发送到服务器之间等待的时间超过 130 秒,就会产生 CommunicationException。

这是完整的异常(exception):

System.ServiceModel.CommunicationException was unhandled by user code
HResult=-2146233087
Message=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 '23:59:59.9110000'.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.WebRequestOutputStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.BufferedStream.Write(Byte[] array, Int32 offset, Int32 count)
at System.Xml.XmlStreamNodeWriter.FlushBuffer()
at System.Xml.XmlStreamNodeWriter.GetBuffer(Int32 count, Int32& offset)
at System.Xml.XmlUTF8NodeWriter.InternalWriteBase64Text(Byte[] buffer, Int32 offset, Int32 count)
at System.Xml.XmlBaseWriter.WriteBase64(Byte[] buffer, Int32 offset, Int32 count)
at System.Xml.XmlDictionaryWriter.WriteValue(IStreamProvider value)
at System.ServiceModel.Dispatcher.StreamFormatter.Serialize(XmlDictionaryWriter writer, Object[] parameters, Object returnValue)
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Stream stream)
at System.ServiceModel.Channels.HttpOutput.WriteStreamedMessage(TimeSpan timeout)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.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 WcfService.IStreamingService.SendStream(MyStreamUpRequest request)
at Client.Program.<Main>b__0() in c:\Users\jpierson\Documents\Visual Studio 2012\Projects\WcfStreamingTest\Client\Program.cs:line 44
at System.Threading.Tasks.Task.Execute()
InnerException: System.IO.IOException
HResult=-2146232800
Message=Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.
Source=System
StackTrace:
at System.Net.Sockets.NetworkStream.MultipleWrite(BufferOffsetSize[] buffers)
at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.ConnectStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.ServiceModel.Channels.BytesReadPositionStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.WebRequestOutputStream.Write(Byte[] buffer, Int32 offset, Int32 count)
InnerException: System.Net.Sockets.SocketException
HResult=-2147467259
Message=An existing connection was forcibly closed by the remote host
Source=System
ErrorCode=10054
NativeErrorCode=10054
StackTrace:
at System.Net.Sockets.Socket.MultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.MultipleWrite(BufferOffsetSize[] buffers)
InnerException:

由于连接不活动,服务器似乎过早地关闭了连接。如果我改为给服务器一个脉冲,即使一次一个字节,那么我永远不会得到这个异常,我可以继续无限期地传输数据。我构建了一个非常简单的示例应用程序来演示这一点,它使用带有 Streamed transferMode 的 basicHttpBinding,我在客户端的自定义流实现中插入了一个人工延迟,延迟 130 秒。这模拟了类似于缓冲区运行不足的情况,在这种情况下,我在客户端的服务调用中提供的流没有足够快地将数据提供给 WCF 基础结构,无法满足某种似乎在 130 秒左右的无法识别的超时值标记。

使用 WCF 服务跟踪工具,我可以找到一个 HttpException,并显示一条消息:“客户端已断开连接,因为基础请求已完成。不再有可用的 HttpContext。”

从 IIS Express 跟踪日志文件中,我看到一个条目显示“由于线程退出或应用程序请求,I/O 操作已中止。(0x800703e3)”

我已将服务器和客户端超时配置为使用远超过 130 秒标记的值来排除它们。我已经在 IIS Express 中尝试了 idleTimeout 以及许多与 ASP.NET 相关的超时值,以便发现这个问题来自哪里,但到目前为止还没有运气。到目前为止我能找到的最好的信息是 comment in the FireFox issue tracker由描述在 WCF 体系结构之外工作的类似问题的开发人员提供。出于这个原因,我猜这个问题可能更具体地与 IIS7 或 Windows Server 相关。

服务器 Web.config 上的自定义绑定(bind)
<binding name="myHttpBindingConfiguration"
closeTimeout="02:00:00"
openTimeout="02:00:00"
receiveTimeout="02:00:00"
sendTimeout="02:00:00">
<textMessageEncoding messageVersion="Soap11" />
<httpTransport maxBufferSize="65536"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="Streamed" />
</binding>

代码中的客户端配置:
    var binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = _maxReceivedMessageSize;
binding.MaxBufferSize = 65536;
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
binding.TransferMode = TransferMode.Streamed;
binding.ReceiveTimeout = TimeSpan.FromDays(1);
binding.OpenTimeout = TimeSpan.FromDays(1);
binding.SendTimeout = TimeSpan.FromDays(1);
binding.CloseTimeout = TimeSpan.FromDays(1);

为了响应 wals 的想法,尝试通过自行托管我的服务来查看我是否得到任何不同的结果,我想补充一点,我这样做了,发现我得到的结果与在 IIS 中托管时相同。这是什么意思?我的猜测是,这意味着问题出在 WCF 或 Windows 的底层网络基础结构中。我使用的是 Windows 7 64 位,我们通过运行各种客户端并在 Windows 2008 Server 上运行服务部分发现了这个问题。

2013-01-15 更新

当我意识到 WCF 在 Windows 7 上的自托管场景中使用 HTTP.sys 时,我发现了一些新线索,这要归功于 DarkWanderer。这让我研究了我可以为 HTTP.sys 配置什么以及人们报告的问题类型对于 HTTP.sys,这听起来与我所经历的相似。这将我带到位于 C:\Windows\System32\LogFiles\HTTPERR\httperr1.log 的日志文件,该文件似乎记录了 HTTP.sys 的特定类型的 HTTP 问题。在此日志中,我每次运行测试时都会看到以下类型的日志条目。

2013-01-15 17:17:12 127.0.0.1 59111 127.0.0.1 52733 HTTP/1.1 POST /StreamingService.svc - - Timer_EntityBody -



因此,要找出可能导致 Timer_EntityBody 的条件。错误以及 IIS7 或其他地方的哪些设置可能会影响何时以及是否发生该错误。

来自 official IIS webiste :

The connection expired before the request entity body arrived. When it is clear that a request has an entity body, the HTTP API turns on the Timer_EntityBody timer. Initially, the limit of this timer is set to the connectionTimeout value. Each time another data indication is received on this request, the HTTP API resets the timer to give the connection more minutes as specified in the connectionTimeout attribute.



尝试按照上述引用在 IIS Express 的 applicationhost.config 中建议修改 connectionTimeout 属性似乎没有任何区别。也许 IIS Express 会忽略此配置并在内部使用硬编码值?我自己尝试了一些东西,我发现添加了新的 netsh http 命令来显示和添加超时值,所以我想出了以下命令,但不幸的是,这样做似乎对这个错误也没有任何影响。

netsh http add timeout timeouttype=IdleConnectionTimeout value=300

最佳答案

事实证明,这个问题是由 Connection Timeout 引起的。 HTTP.sys 使用的值,并且可以通过 IIS 管理器通过单个站点的高级设置来指定。默认情况下,此值配置为在 120 秒内未收到 header 和正文时使连接超时。如果接收到来自正文的数据脉冲,则服务器在超时值内重新启动计时器(Timer_EntityBody),然后重置计时器以等待其他数据。

Connection Time-out setting in IIS

这就像 the documentation关于 Timer_EntityBody 连接超时指定,但是很难确定,因为无论文档说什么,IIS Express 似乎都忽略了 applicationhost.config 的限制元素中指定的 connectionTimeout 值。为了确定这一点,我必须在我的开发机器上安装完整版本的 IIS,并在将我的站点托管在那里之后修改上面的设置。

由于我们在 Windows 2008 上的 IIS 下托管实际服务,因此上述解决方案对我有用,但问题仍然是在您是自托管的情况下如何正确修改连接超时值。

关于wcf - 什么 130 秒超时正在杀死我的 WCF 流服务调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14266854/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com