什么130秒超时正在杀死我的WCF流媒体服务电话? [英] What 130 second timeout is killing my WCF streaming service call?

查看:330
本文介绍了什么130秒超时正在杀死我的WCF流媒体服务电话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Just recently I started to investigate a tricky problem with WCF streaming in which a CommunicationException is produced if the client waits for any longer than 130 seconds in between sends to the server.

以下是完整的例外:

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: 

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

It appears that the server has closed the connection prematurely due to inactivity on the connection. If I instead give a pulse to the server, even one byte at a time, then I never get this exception and I can continue to transfer data indefinitely. I've constructed a very simple example application to demonstrate this which uses basicHttpBinding with Streamed transferMode and I insert an artificial delay from within a custom stream implementation on the client that delays for 130 seconds. This simulates something similar to a buffer under-run condition in which the stream provided in my service call from the client is not feeding the data to the WCF infrastructure quick enough to satisfy some sort of unidentifiable timeout value that appears to be around the 130 second mark.

使用WCF服务跟踪工具我能够找到一条HttpException,其消息显示客户端因基础请求已完成而断开连接。不再有可用的HttpContext。

Using the WCF service tracing tools I'm able to find an HttpException with the a message that reads "The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available."

从IIS Express跟踪日志文件中,我看到一条条目:I / O操作因为任何一个而中止线程退出或应用程序请求。(0x800703e3)

From the IIS Express trace log file I see an entry that says "The I/O operation has been aborted because of either a thread exit or an application request. (0x800703e3)"

我已将服务器和客户端超时配置为使用超过130秒标记的值,以排除它们。我已经在IIS Express中尝试了idleTimeout以及一系列与ASP.NET相关的超时值,以便发现这个问题的来源,但到目前为止还没有运气。到目前为止,我能找到的最佳信息是开发人员在FireFox问题跟踪器中发表评论。描述了在WCF体系结构之外工作的类似问题。出于这个原因,我猜这个问题可能与IIS7或可能是Windows Server有关。

I've configured both server and client timeouts to use a value well over the 130 second mark just to rule them out. I've tried idleTimeout in IIS Express and a host of ASP.NET related timeout values too in order to discover where this issue is coming from but so far no luck. The best information I can find so far is a comment in the FireFox issue tracker by a developer that describes a similar problem working outside of the WCF architecture. For this reason I'm guessing the issue may be more related specifically to IIS7 or possibly Windows Server.

服务器Web.config上的自定义绑定

Custom binding on server Web.config

<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上运行服务部分来发现此问题。

In response to wals idea to try to see if I get any different results by self hosting my service I want to add that I did so and found that I get the same results as when hosting in IIS. What does this mean? My guess is that this means the issue is either in WCF or in the underlying networking infrastructure in Windows. I'm using Windows 7 64 bit and we've discovered this issue by running various clients and running the service portion on a Windows 2008 Server.

一旦我意识到WCF在Windows 7上的自托管方案中使用了HTTP.sys,我发现了一些新的线索,感谢DarkWanderer。这让我看到了什么我可以配置HTTP.sys以及人们报告的HTTP.sys类似于我正在经历的类型的问题。这导致我找到位于 C:\ Windows \ System32 \ LogFiles \HTTPERR \httperr1.log 的日志文件,它似乎记录了HTTP部分的特定类型的HTTP问题。 SYS。在这个日志中,每次运行测试时都会看到以下类型的日志条目。

I found some new clues thanks to DarkWanderer once I realized that WCF uses HTTP.sys underneath in self-hosting scenarios on Windows 7. This got me looking into what I could configure for HTTP.sys and also what type of issues people are reporting that for HTTP.sys that sound similar to what I'm experiencing. This lead me to a log file located at C:\Windows\System32\LogFiles\HTTPERR\httperr1.log which appears to log specific types of HTTP issues on the part of HTTP.sys. In this log I see the following type of log entry each time I run my test.


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

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或其他地方的哪些设置可能会影响何时以及是否发生错误。

So it's down to finding what conditions could cause a Timer_EntityBody error and what settings in IIS7 or elsewhere may have a bearing on when and if that error occurs.

来自官方IIS网站


连接在请求实体主体到达之前已过期。当
清楚表明请求具有实体主体时,HTTP API将打开
Timer_EntityBody计时器。最初,此计时器的限制设置为
connectionTimeout值。每次在此请求上收到另一个数据指示是
时,HTTP API会重置计时器,以便在connectionTimeout
属性中指定
连接更多分钟。

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.

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

Trying to modify the connectionTimeout attribute as the reference above suggests for in applicationhost.config for IIS Express doesn't seem to make any difference. Perhaps IIS Express ignores this configuration and uses a hard coded value internally? Trying something on my own I discovered that there are new netsh http commands added to show and add timeout values so giving that I go I came up with the following command but unfortunately doing so didn't seem to have any effect on this error either.


netsh http add timeout timeouttype = IdleConnectionTimeout value = 300

netsh http add timeout timeouttype=IdleConnectionTimeout value=300


推荐答案

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

It turns out that this issue was caused by the Connection Timeout value used by HTTP.sys and that can be specified through IIS Manager through the Advanced Settings for the individual site. This value is configured by default to timeout a connection when both the header and body haven't been received within 120 seconds. If a pulse of data from the body is received then the server restarts a timer (Timer_EntityBody) within the timeout value then the timer is reset to wait for additional data.

< img src =https://i.stack.imgur.com/5hu24.pngalt =IIS中的连接超时设置>

这只是作为有关 Timer_EntityBody 的文档 connectionTimeout 指定,但很难确定,因为看起来IIS Express忽略了 applicationhost.config 中的limits元素中指定的connectionTimeout值,无论文档说什么。为了确定这一点,我必须在我的开发机器上安装完整版本的IIS,并在托管我的网站后修改上面的设置。

This is just as the documentation concerning Timer_EntityBody and connectionTimeout specifies, however it was hard to pinpoint because it appears that IIS Express ignores the connectionTimeout value specified in the limits element in applicationhost.config regardless of what the documentation says. In order to determine this I had to install the full version of IIS on my development machine and modify the setting above after hosting my site there.

由于我们在Windows 2008上的IIS下托管真实服务,上述解决方案对我有用,但问题仍然是如何正确修改案例中的连接超时值你在哪里自我托管。

Since we are hosting the real service under IIS on Windows 2008 the above solution will work for me however the question still remains on how to properly modify the Connection Timeout value in cases where you are Self Hosting.

这篇关于什么130秒超时正在杀死我的WCF流媒体服务电话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆