WSHttpBindingを使用しているときにサーバー上に蓄積されるWCF同時要求
-
08-07-2019 - |
質問
WSHttpBindingを使用してHTTPで通信しているWCFクライアント/サーバーアプリがあります。
サーバーのセットアップ:標準のWCF ServiceHost
を使用したセルフホスティング。
私の実際のサービスクラスの属性は次のとおりです。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerSession,
UseSynchronizationContext = false)]
クライアントのセットアップ:同期サービス呼び出しを使用して、Visual Studioで生成されたクライアントプロキシを使用します(サーバーが完全に応答するまでブロックします)。
シナリオ:
サーバーで実行するのに20秒かかる特定のメソッド呼び出しが1つあります。クライアントはこのメソッドを別のスレッドで呼び出すため、保持されません。proxy.call_server_method
は、WCFがサーバー上の別のスレッドでも実行することを意味します。
この理論は、ConcurrencyMode.Multiple
を使用するようにアプリを構成すると、すべてが正常に機能するという事実によってサポートされています。
問題:
NetTcpBinding
を使用するようにアプリを構成すると、この長いメソッド呼び出しにより、http要求が「バックアップ」されます。この動作は、ログを検査することと、fiddlerを使用してHTTPリクエストをデバッグすることの両方で検証しました。
例:
- クライアントはバックグラウンドスレッドで20秒間のリクエストを開始します
- クライアントはフォアグラウンドスレッドでリクエストBとCを開始します
- リクエストBとCはサーバーに送信され、20秒のリクエストが完了するまで処理されません
しかし時々:
- リクエストBとCは、20秒のリクエストが返されるまで(送信されることはありません)送信されません(これはまれです)。
- 注:クライアントのapp.configで
WSHttpBinding
を設定すると、この(表示される)動作が停止します。
- 注:クライアントのapp.configで
- リクエストBは送信され、すぐにレスポンスを受信しますが、リクエストCは20秒が完了するまで保留されます(これはまれです)
問題を実証するフィドラーのタイムラインは次のとおりです。(クリックすると大きなバージョンになります)
ご覧のとおり、リクエストはすべてサーバーでバックアップされています。 20秒のリクエストが完了すると、すべてのレスポンスがあふれますが、保留されていない リクエストがあることに注意してください...
つまり、質問:
- ここで何が起こっているのですか?
<add address="*" maxconnection="100"/>
を使用して正常に機能し、!syncblk
を使用して機能しないのはなぜですか? - 一貫性のない動作が必要な理由
- 修正するにはどうすればよいですか?
注:
- サーバーがロックされていません。ブレークポイントを設定して
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" />
を使用しましたが、ロックが保持されていないことを一貫して報告しています。 - それは私のスレッドではありません(そうでなければNetTcpBindingは動作しません)
- サーバーのapp.configで<=>を設定しています
- 20秒の呼び出しはタイマーを待機しているだけで、CPU、ディスク、またはネットワークをスラッシングしていません
- 非同期呼び出しを使用するようにアプリケーションを再設計する必要のないソリューションを好む...それは多くのレガシーコードであり、私が理解していないものをいじりたくない。
解決 3
[最終的な解決策を他のユーザーに示す自己回答]
最終的に、私はこれを解決することができませんでした。
最終的な解決策は、アプリを本番環境でWSHttpBinding
からNetTcpBinding
に切り替えることでした-パフォーマンスの理由から、いずれにしろこれを最終的に行うことを計画していました。
これは、<=>に黒いマークを残すため、保証される場合と保証されない場合があるため、かなり残念です。誰かが溝を捨てることを伴わない解決策を思いついた場合、<=>、私はそれについて知りたいです
他のヒント
WCF(.NetまたはWindowsのこと)の外側には、最大2つの同時送信HTTP接続のみを許可するデフォルトのスロットルがあります。残念ながら、私は一生そのものの名前(およびapp.configまたはアプリをオーバーライドするために何を入れたか)を思い出せません。リクエストがクライアントを離れるのが見えず、それがHTTPのみであるということを考えると、<!> quot; that thing <!> quot;にヒットしていると思います。名前を探し続けます。
更新:見つかった-クライアントでこれを試してください(ただし、「2」を大きな数値に変更してください):
<configuration>
<system.net>
<connectionManagement>
<add address = "*" maxconnection = "2" />
</connectionManagement>
</system.net>
</configuration>
IIS / ASP.NETでホストされるJSONサービスでもまったく同じ症状が見られました。
根本的な原因は、WCFではなく、リクエストを同期するASP.NETでした。同時WCFメソッドを取得するには、セッションレベルを(アプリケーションレベルで)無効にする必要がありました。
Web.config:
<system.web> <sessionState mode="Off" /> </system.web>
このサービスはwsHttpBindingではなくwebHttpBindingを使用していることに注意してください。したがって、これがOrionの問題を解決するかどうかはわかりません。
プロトコルの制限に達したと思うので、クライアントマシンの標準設定を変更する必要があります。
http://support.microsoft.com/kb/183110
http://support.microsoft.com/kb/282402
WSHttpBindingは、リクエストを発行するときにWinINET設定を使用すると思います。
BasicHttpBindingに変更した場合、機能しますか?
そうです、これはあなたの問題です、セッションの調整、お尻に私をかみました。
同時呼び出しを可能にするために、呼び出しごとのサービスでConcurrencyMode.Multipleを使用することを検討してください 呼び出し。
忘れてしまった-注文できた? HTTP経由のRMは順序を保持しますが、Tcpセッションは順序を保持しません(明示的に要求しない限り)。順序付き/順序なしセッションを説明するサービス契約に属性はありますか(忘れました)。
確かではありませんが、silverlightアプリケーションからの同時呼び出しの問題はブラウザー接続管理に関連している場合があります。私にとっての解決策は、App.xaml.csのApplication_Startupメソッドに以下のように記述することでした: http://weblogs.asp.net/olakarlsson/simultaneously-calling-multiple-methods-on-a-wcf-service-from-silverlight
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);