WCFを使用してC#でクライアント/サーバーアプリケーションを作成しています。すべてのテストは正常に行われましたが、サービスを展開するとすぐに、サーバーとの通信にランダムな問題があることに気付きました。デバッグを有効にすると、サーバーで次のようなメッセージが表示されました。
The communication object, System.ServiceModel.Channels.ServerReliableDuplexSessionChannel, cannot be used for communication because it has been Aborted.
パターンは次のようになります。
- クライアントがクエリを送信しています
- サービスはクエリを処理しています
- サービスは何かを送り返しています
- アクティビティの境界は「停止」レベルです-すべてが正常に見えます
- 信頼できるセッションのinactivityTimeoutを最後の連絡の日時に追加すると、サービスによってスローされた例外のタイムスタンプが得られます
アプリケーションは次のようになります。サービスインスタンスは、データベースと対話するためのAPIメソッドを提供し、タイプは「netTcpBinding」です。複数のクライアント(約40)が接続され、サービスからランダムにメソッドを呼び出します。クライアントは、何も送受信しなくても、数日間開いたままにすることができます。
関連するビットは次のとおりです。
サービス:
[ServiceContract(CallbackContract = typeof(ISVCCallback), SessionMode = SessionMode.Required)]
[ExceptionMarshallingBehavior]
...
と
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext=true)]
public class SVCService : ISVC
...
サービス構成:
<behaviors>
<serviceBehaviors>
<behavior name="behaviorConfig">
<serviceMetadata httpGetEnabled="false" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="1000"
maxConcurrentInstances="50" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpBinding" closeTimeout="00:01:00" openTimeout="00:10:00"
receiveTimeout="23:59:59" sendTimeout="00:01:30" transferMode="Buffered"
listenBacklog="1000" maxBufferPoolSize="671088640" maxBufferSize="671088640"
maxConnections="1000" maxReceivedMessageSize="671088640" portSharingEnabled="true">
<readerQuotas maxStringContentLength="671088640" maxArrayLength="671088640"
maxBytesPerRead="671088640" />
<reliableSession inactivityTimeout="23:59:59" enabled="true" />
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>
クライアント構成:
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_ISVC" closeTimeout="00:01:00" openTimeout="00:10:00"
receiveTimeout="23:59:59" sendTimeout="00:01:30" transactionFlow="false"
transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="1000"
maxBufferPoolSize="671088640" maxBufferSize="671088640" maxConnections="1000"
maxReceivedMessageSize="671088640">
<readerQuotas maxStringContentLength="671088640" maxArrayLength="671088640"
maxBytesPerRead="671088640" />
<reliableSession ordered="true" inactivityTimeout="23:59:59"
enabled="true" />
<security mode="None">
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
ここに何か問題がありますか?これらの種類のアプリケーションに最適な構成は何ですか?
アップデート:
私は1つのことに遭遇しました:
あるサービス契約では、何かを変更して、接続されているすべてのクライアントに通知します。少なくとも私のテストでは、通常は正常に機能します。しかし、最後の「クラッシュ」または「フリーズ」でログを調べたところ、最新の関数では、コールバックコントラクトを使用してクライアントに通知していることがわかりました。
そこでやりたいこと:データベースに何かを保存し、最後に接続されているすべてのクライアントに変更を通知します。接続されているクライアントのリストはもう最新ではなく、このステップでタイムアウトになると思います。
ここで問題となるのは、これらのタイムアウトを回避する方法です。
- サービスでスレッドを使用する必要がありますか?サービスコールが終了するとすぐにスレッドが強制終了されると思いますが、私はここにいますか?
- すべてのコールバック通知を行う静的キュー関数を実装できます(これはMarc_Sが提案したものです)
- サーバー内の接続ドロップを確実に検出する方法はありますか?