.NET 3.5、VS2008、BasicHttpBindingを使用したWCFサービス
WindowsサービスでホストされているWCFサービスがあります。アップグレードや定期的なメンテナンスなどの理由でWindowsサービスがシャットダウンした場合、WCFサービスを正常にシャットダウンする必要があります。WCFサービスには、完了するまでに最大数秒かかる可能性のあるメソッドがあり、通常のボリュームは1秒あたり2〜5回のメソッド呼び出しです。新しい呼び出しを拒否しながら、以前に呼び出したメソッドを完了できるようにWCFサービスをシャットダウンする必要があります。このようにして、約5〜10秒でクワイエット状態に到達し、Windowsサービスのシャットダウンサイクルを完了することができます。
ServiceHost.Closeを呼び出すことは正しいアプローチのように見えますが、進行中のメソッドが完了するのを待たずに、クライアント接続をすぐに閉じます。私のWCFサービスはそのメソッドを完了しますが、クライアントが既に切断されているため、応答を送信する相手がいません。これは、この質問によって提案された解決策です。
イベントのシーケンスは次のとおりです。
- クライアントは、VSで生成されたプロキシクラスを使用して、サービスでメソッドを呼び出します
- サービスがサービスメソッドの実行を開始します
- サービスはシャットダウンの要求を受け取ります
- サービスはServiceHost.Close(またはBeginClose)を呼び出します
- クライアントが切断され、System.ServiceModel.CommunicationExceptionを受け取ります
- サービスはサービスメソッドを完了します。
- 最終的に、サービスは(アプリケーションロジックを介して)実行する作業がなくなったことを検出し、終了します。
私が必要としているのは、クライアント接続を開いたままにして、クライアントがサービスメソッドが正常に完了したことを認識できるようにすることです。現在、接続が閉じられているだけで、サービスメソッドが正常に完了したかどうかはわかりません。WCFを使用する前は、ソケットを使用していましたが、ソケットを直接制御することでこれを行うことができました。(つまり、受信と送信を実行している間にAcceptループを停止します)
アップストリームファイアウォールがトラフィックを別のホストシステムに転送できるように、ホストHTTPポートを閉じることが重要ですが、既存の接続は開いたままにして、既存のメソッド呼び出しを完了できるようにします。
WCFでこれを実現する方法はありますか?
私が試したこと:
- ServiceHost.Close()-クライアントをすぐに閉じます
- ServiceHost.ChannelDispatchers-それぞれでListener.Close()を呼び出します-何もしないようです
- ServiceHost.ChannelDispatchers-それぞれでCloseInput()を呼び出します-クライアントをすぐに閉じます
- ServiceHost.OnClosing()をオーバーライドします-閉じることができると判断するまで閉じるを遅らせることができますが、この間は新しい接続が許可されます
- ここで説明する手法を使用して、エンドポイントを削除します。これはすべてを一掃します。
- ネットワークスニファを実行してServiceHost.Close()を監視します。ホストは接続を閉じるだけで、応答は送信されません。
ありがとう
編集:残念ながら、フィールドのクライアントはすでに展開されているため、システムがシャットダウンしているというアプリケーションレベルのアドバイザリ応答を実装できません。(私はサービスのみを制御し、クライアントは制御しません)
編集:Redgate Reflectorを使用して、MicrosoftのServiceHost.Closeの実装を確認しました。残念ながら、internal
コードがアクセスできないいくつかのヘルパークラスを呼び出します。
編集:探していた完全な解決策は見つかりませんでしたが、サービスメソッドを入力する前にIMessageDispatchInspectorを使用してリクエストを拒否するというBenjaminの提案が最も近かったです。