Какой 130-секундный тайм-аут убивает мой вызов потоковой службы WCF?

недавно я начал исследовать сложную проблему с потоковой передачей WCF, в которой создается исключение CommunicationException, если клиент ждет более 130 секунд между отправками на сервер.

вот полное исключение:

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:UsersjpiersonDocumentsVisual Studio 2012ProjectsWcfStreamingTestClientProgram.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 с потоковым transferMode, и я вставляю искусственную задержку из пользовательской реализации потока на клиенте, которая задерживается на 130 секунд. Это имитирует что-то похожее на состояние буфера при запуске, в котором поток, предоставленный в моем вызове службы от клиента, не подает данные в инфраструктуру WCF достаточно быстро, чтобы удовлетворить какой-то вид неопознанного значения тайм-аута, которое, по-видимому, составляет около 130 секунд.

используя инструменты трассировки службы WCF, я могу найти HttpException с сообщением, которое гласит: "клиент отключен, потому что базовый запрос был завершен. Больше нет доступного HttpContext."

из файла журнала трассировки IIS Express я вижу запись, в которой говорится: "операция ввода-вывода была прервана из-за выхода потока или запроса приложения. (0x800703e3)"

Я настроил как серверные, так и клиентские тайм-ауты, чтобы использовать значение более 130 секунд, чтобы исключить их. Я пробовал idleTimeout в IIS Express и множество ASP.NET связанные значения тайм-аута тоже, чтобы узнать, откуда эта проблема, но до сих пор не повезло. Лучшая информация, которую я могу найти до сих пор, это комментарий в Firefox проблема tracker разработчиком, который описывает аналогичную проблему, работающую вне архитектуры WCF. Для по этой причине я предполагаю, что проблема может быть связана конкретно с IIS7 или, возможно, Windows Server.

пользовательская привязка на веб-сервере.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.

2013-01-15 обновление

Я нашел несколько новых подсказок благодаря DarkWanderer, как только понял, что WCF использует HTTP.sys внизу в сценариях самостоятельного размещения в Windows 7. Это заставило меня посмотреть, что я мог бы настроить для HTTP.sys, а также какие проблемы люди сообщают об этом для HTTP.sys этот звук похож на то, что я испытываю. Это приведет меня к файлу журнала, расположенному по адресу C:WindowsSystem32LogFilesHTTPERRhttperr1.log который, как представляется, регистрирует определенные типы проблем HTTP со стороны 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 или в другом месте могут иметь отношение к тому, когда и если эта ошибка возникает.

С Официальный веб-сайт IIS:

подключения истекло до запроса прибытия тела. Когда это ясно, что запрос имеет тело сущности, HTTP API включает Timer_entitybody таймер. Изначально предел этот таймер значение connectionTimeout. Каждый раз другая индикация данных полученный по этому запросу HTTP API сбрасывает таймер, чтобы дать подключение больше минут, как указано в connectionTimeout атрибут.

попытка изменить атрибут connectionTimeout как ссылка выше предлагает Для в applicationhost.конфигурация для IIS Express, похоже, не имеет никакого значения. Возможно, IIS Express игнорирует эту конфигурацию и использует жесткий закодированное значение внутри? Попробовав что-то самостоятельно, я обнаружил, что есть новые команды netsh http, добавленные для отображения и добавления значений таймаута, так что я иду, я придумал следующую команду, но, к сожалению, это, похоже, не повлияло на эту ошибку.

netsh http добавить тайм-аут timeouttype=IdleConnectionTimeout значение=300

5 ответов


получается, что эта проблема была вызвана Время Ожидания Соединения значение, используемое HTTP.sys и это можно указать через диспетчер IIS с помощью дополнительных параметров для отдельного сайта. Это значение по умолчанию настроено на тайм-аут соединения, Если заголовок и тело не были получены в течение 120 секунд. Если импульс данных из тела получен, то сервер перезапускает таймер (Timer_EntityBody) в пределах значения тайм-аута, то таймер сбрасывается на ждать дополнительных данных.

Connection Time-out setting in IIS

Это как документация о Timer_EntityBody и connectionTimeout указывает, однако было трудно определить, потому что кажется, что IIS Express игнорирует значение connectionTimeout, указанное в элементе limits в applicationhost.config независимо от того, что сказано в документации. Чтобы определить это, мне пришлось установить полный версия IIS на моей машине разработки и измените параметр выше после размещения моего сайта там.

Так как мы размещаем реальную службу под IIS на Windows 2008 вышеупомянутое решение будет работать для меня, однако вопрос по-прежнему остается о том, как правильно изменить значение тайм-аута соединения в случаях, когда вы самостоятельно хостинг.


судя по ошибке:

подключение к сокету было прервано. Это может быть вызвано ошибкой обработка сообщения или превышение тайм-аута приема удаленный узел или проблема с базовым сетевым ресурсом. Локальный сокет тайм-аут был '23:59:59.9110000'

похоже, что это простой тайм-аут TCP.

вы можете проверить это, запустив приложение как самостоятельное, а затем выполнив эту команду в консоль:

netstat -no |find "xxxxx"

где xxxxx-это PID вашего серверного процесса. Эта команда покажет вам соединения, установленные вашим сервером, и будет обновляться каждую секунду.

попробуйте подключиться к клиенту и посмотреть, что произойдет. Скорее всего, вы увидите "CLOSE_WAIT" или "TIME_WAIT" на вашем соединении примерно через 100-120 секунд - что будет означать, что он был прерван из-за таймаута.

Это можно исправить, добавив следующее к вашему config:

<httpTransport maxBufferSize="65536"                        
             maxReceivedMessageSize="2147483647"
             maxBufferPoolSize="2147483647"
             transferMode="Streamed"
             keepAliveEnabled="true" /> <!-- Here -->

параметр объяснил здесь


возможно, но... Проверьте пул приложений IIS, включен ли Ping. Это в расширенных настройках, группировка моделей процессов.


попробуйте это, для меня это решило проблему. Проблема в том, что базовое ядро http.у sys есть собственный тайм-аут, и он разорвет соединение.

http://mmmreddy.wordpress.com/2013/07/11/wcf-use-of-http-transport-sharing-persistent-tcp-sessions/

netsh http add timeout timeouttype=idleconnectiontimeout value=120

вы http://support.microsoft.com/kb/946086 ?

Я наблюдал такие прерывания потоковой передачи в моих ISAPI-расширениях. После выключения буферизация в IIS 7 Согласно этой заметке suppport, everthing работал штраф.