17

つい最近、クライアントがサーバーへの送信の間に130秒以上待機すると、CommunicationExceptionが生成されるWCFストリーミングのトリッキーな問題の調査を開始しました。

完全な例外は次のとおりです。

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: 

接続が非アクティブであるため、サーバーが接続を途中で閉じたようです。代わりに、一度に1バイトでもサーバーにパルスを与えると、この例外が発生することはなく、データを無期限に転送し続けることができます。Streamed transferModeでbasicHttpBindingを使用する非常に単純なサンプルアプリケーションを作成し、クライアントのカスタムストリーム実装内から130秒間遅延する人為的な遅延を挿入しました。これは、クライアントからのサービスコールで提供されたストリームが、約130秒のように見えるある種の識別できないタイムアウト値を満たすのに十分な速さでデータをWCFインフラストラクチャに供給していない、バッファアンダーラン状態に似たものをシミュレートします。マーク。

WCFサービストレースツールを使用すると、「基になる要求が完了したため、クライアントが切断されました。使用可能なHttpContextがなくなりました。」というメッセージを含むHttpExceptionを見つけることができます。

IIS Expressトレースログファイルから、「スレッドの終了またはアプリケーション要求のいずれかが原因でI / O操作が中止されました。(0x800703e3)」というエントリが表示されます。

サーバーとクライアントの両方のタイムアウトを、それらを除外するためだけに130秒のマークをはるかに超える値を使用するように構成しました。この問題がどこから来ているのかを発見するために、IIS ExpressとASP.NET関連のタイムアウト値のホストでidleTimeoutを試しましたが、これまでのところ運がありません。私がこれまでに見つけた最高の情報は、開発者によるFireFox課題追跡システムのコメントであり、WCFアーキテクチャの外部で機能する同様の問題について説明しています。このため、この問題は特にIIS7またはWindowsServerに関連している可能性があると思います。

サーバー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の基盤となるネットワークインフラストラクチャにあることを意味します。私はWindows764ビットを使用していますが、さまざまなクライアントを実行し、Windows 2008 Serverでサービス部分を実行することで、この問題を発見しました。

2013年1月15日更新

WCFがWindows7のセルフホスティングシナリオで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または他の場所のどの設定がそのエラーが発生するかどうかに関係する可能性があるかどうかを見つけることが重要です。

公式IISWebisteから:

リクエストエンティティの本体が到着する前に接続が期限切れになりました。リクエストにエンティティ本体があることが明らかな場合、HTTPAPIはTimer_EntityBodyタイマーをオンにします。最初は、このタイマーの制限はconnectionTimeout値に設定されています。このリクエストで別のデータ表示が受信されるたびに、HTTP APIはタイマーをリセットして、connectionTimeout属性で指定された分数を接続に与えます。

上記の参照がIISExpressのapplicationhost.configで示唆しているように、connectionTimeout属性を変更しようとしても、違いはないようです。おそらく、IIS Expressはこの構成を無視し、内部でハードコードされた値を使用しますか?自分で何かを試してみると、タイムアウト値を表示および追加するために新しいnetsh httpコマンドが追加されていることがわかりました。そのため、次のコマンドを思いつきましたが、残念ながら、このエラーにも影響がないようです。

netsh http add timeout timeouttype = IdleConnectionTimeout value = 300

4

5 に答える 5

16

この問題は、HTTP.sys で使用される接続タイムアウト値が原因であることが判明しました。この値は、IIS マネージャーの個々のサイトの [詳細設定] で指定できます。この値は、デフォルトで、ヘッダーと本文の両方が 120 秒以内に受信されなかった場合に接続をタイムアウトするように構成されています。本体からのデータのパルスが受信された場合、サーバーはタイムアウト値内でタイマー (Timer_EntityBody) を再起動し、タイマーはリセットされて追加のデータを待ちます。

IIS の接続タイムアウト設定

これは、 Timer_EntityBodyconnectionTimeoutに関するドキュメントで指定されているとおりですが、ドキュメントの内容に関係なく、 IIS Express がapplicationhost.configの limits 要素で指定された connectionTimeout 値を無視しているように見えるため、特定するのは困難でした。これを判断するために、IIS のフル バージョンを開発マシンにインストールし、そこでサイトをホストした後に上記の設定を変更する必要がありました。

Windows 2008 の IIS で実際のサービスをホストしているため、上記のソリューションは機能しますが、セルフ ホスティングの場合に接続タイムアウト値を適切に変更する方法についてはまだ疑問が残ります。

于 2013-01-15T23:45:32.310 に答える
2

エラーから判断すると:

ソケット接続が中止されました。これは、メッセージの処理中にエラーが発生したか、リモート ホストが受信タイムアウトを超過したか、基になるネットワーク リソースの問題が原因である可能性があります。ローカル ソケットのタイムアウトは「23:59:59.9110000」でした

これは単純な TCP タイムアウトのようです。

アプリケーションをセルフホストとして実行し、コンソールで次のコマンドを実行することで確認できます。

netstat -no |find "xxxxx"

ここで、xxxxx はサーバー プロセスの PID です。このコマンドは、サーバーが確立した接続を表示し、毎秒更新します。

クライアントと接続して、何が起こるかを確認してください。ほとんどの場合、約 100 ~ 120 秒後に接続に「CLOSE_WAIT」または「TIME_WAIT」が表示されます。これは、タイムアウトにより中断されたことを意味します。

これは、構成に次を追加することで修正できるはずです。

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

パラメータの説明はこちら

于 2013-01-15T09:50:00.357 に答える
1

おそらく大失敗ですが... Ping が有効になっている場合は、IIS アプリケーション プールを確認してください。詳細設定、プロセス モデルのグループ化にあります。

于 2013-01-10T21:03:59.487 に答える
0

http://support.microsoft.com/kb/946086を検討しましたか?

ISAPI 拡張機能で、このようなストリーミングの割り込みが見られました。このサポート ノートに従って IIS 7 のバッファリングをオフにすると、すべてが正常に機能しました。

于 2013-10-10T21:12:27.277 に答える