WSHttpBinding を使用して HTTP 経由で通信する WCF クライアント/サーバー アプリがあります。
サーバーのセットアップ: 標準の WCF を使用したセルフホスティングServiceHost
。私の実際のサービスクラスは次のように分類されます:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerSession,
UseSynchronizationContext = false)]
クライアント セットアップ:同期サービス呼び出しを使用してビジュアル スタジオで生成されたクライアント プロキシを使用します (proxy.call_server_method
サーバーが完全に応答するまでブロックします)。
シナリオ: サーバー上で実行するのに 20 秒かかる特定のメソッド呼び出しがあります。クライアントはこのメソッドを別のスレッドで呼び出すため、保留されていないため、ConcurrencyMode.Multiple
WCF はサーバー上の別のスレッドでもメソッドを実行する必要があります。
NetTcpBinding
この理論は、アプリを使用するように構成すると、すべてが正常に機能するという事実によって裏付けられています。
問題:
を使用するようにアプリを構成するWSHttpBinding
と、この長いメソッド呼び出しによって http 要求が「バックアップ」されます。ログを調べて、フィドラーを使用して HTTP 要求をデバッグすることで、この動作を確認しました。
例:
- クライアントがバックグラウンド スレッドで 20 秒間のリクエストを開始する
- クライアントはフォアグラウンド スレッドでリクエスト B と C を開始します
- リクエスト B と C はサーバーに送信されますが、サーバーは 20 秒間のリクエストが完了するまでそれらを処理しません。
でも時々:
- リクエスト B と Cは、20 秒のリクエストが返されるまで送信されません(フィドラーにも表示されません) (これはまれです)。
- 注:
<add address="*" maxconnection="100"/>
クライアントの app.config を設定すると、この (ように見える) 現象が発生しなくなりました。
- 注:
- リクエスト B は送信され、すぐに応答を受け取りますが、リクエスト C は 20 秒のリクエストが完了するまで保留されます (これはまれです)。
問題を示すフィドラーからのタイムラインは次のとおりです:(クリックすると拡大版が表示されます)
ご覧のとおり、リクエストはすべてサーバーにバックアップされています。20 秒のリクエストが完了すると、すべてのレスポンスがフラッディングされますが、一部のリクエストが遅延しないことに注意してください...
だから、質問:
- ここで一体何が起こっているのですか?
NetTcpBinding
を使用すると正常に動作し、使用すると動作しないのはなぜWSHttpBinding
ですか? - 一貫性のない動作はなぜですか?
- 修正するにはどうすればよいですか?
ノート:
- サーバー上でロックしていません。ブレークポイントを設定して使用
!syncblk
しましたが、ロックが保持されていないと一貫して報告されます。 - それは私のスレッドではありません (それ以外の場合、NetTcpBinding は機能しません)。
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" />
サーバーのapp.configに設定しました- 20 秒の呼び出しはタイマーで待機しているだけであり、CPU、ディスク、またはネットワークをスラッシングしていません。
- 非同期呼び出しを使用するためにアプリケーションを再構築する必要のないソリューションが望ましいと思います...それは大量のレガシー コードであり、理解できないものをいじりたくないのです。