25

自明な自己 Q/A で申し訳ありませんが、この情報は広く誤解されており、ほとんどの場合、間違った回答がされています。そこで、この問題に対する決定的な答えを探している人々のために、この情報をここに掲載したいと思いました。

とはいえ、まだ特定できていない情報もあります。これを質問の最後に置きます(前文に興味がない場合はスキップしてください)。

WCF NetTcp Duplex Reliable Session を正しく構成するにはどうすればよいですか?

このトピックに関して多くの質問と回答があり、それらのほとんどすべてが構成での設定inactivityTimeout="Infinite"を提案しています。これは、特に NetTcp の場合、実際には正しく機能していないようです (WSDualHttp バインディングでは正しく機能する可能性がありますが、私はそれらを使用したことがありません)。

これに関連することが多いその他の問題がいくつかあります。たとえば、クライアントまたはサーバーが予期せず切断された後、チャネルに障害が発生しない、10 分後にチャネルが切断される、チャネルがランダムに切断される... チャネルを開こうとすると例外がスローされる... できない同じエンドポイントでメタデータを構成...

注意: 以下に重要な概念が 2 つあります。インフラストラクチャ メッセージは、WCF の通信方法の内部にあり、物事をスムーズに実行し続けるためにフレームワークによって使用されます。操作メッセージは、ネットワーク経由でメッセージを送信するなど、アプリが何かを行ったために発生するメッセージです。インフラストラクチャ メッセージはアプリからはほとんど見えませんが (ただし、バックグラウンドで発生します)、操作メッセージはアプリが実行したアクションの結果です。

苦労して試行錯誤して得た情報。

  • Infiniteすべての状況で有効な構成設定ではないようです (もちろん、ビジュアル スタジオの検証スキーマはそれを認識していません)。
  • InfiniteIntConverterと と呼ばれる 2 つの特別な構成コンバーターがあり、値をまたはに変換するために機能InfiniteTimeSpanConverterすることがありますが、これが有効であると思われる状況をまだ理解していません。さらに、構成で許可するライブラリもあれば、許可しないライブラリもあるようです。そのため、構成のある部分では成功しても、別の部分では失敗する可能性があります。InfiniteInt.MaxValueTimeSpan.MaxValueInfinite
  • クライアントとサーバーの両方で、 と の両方を構成 する必要があります。これらの値は同じである必要はありませんが、同じでないと混乱を招く可能性があるため、同じにする必要があります。(技術的には、必要に応じてデフォルト値のままにしておくことができますが、その値とその機能に注意する必要があります)inactivityTimeoutreceiveTimeoutinactivityTimeout
  • inactivityTimeout絶対に大きな値に設定しないInfiniteでくださいTimeSpan.MaxValue
  • inactivityTimeoutには 2 つの機能があります (これは広く理解されていません)。最初の関数は、「インフラストラクチャ」または「操作」メッセージを受信せずにチャネルで経過できる最大時間を定義します。2 番目の関数は、インフラストラクチャ メッセージが送信される期間を定義します (指定された時間の半分)。タイムアウト期間中にインフラストラクチャまたは操作メッセージを受信しなかった場合、接続は中止されます。
  • receiveTimeout操作メッセージ間でのみ経過できる最大時間を指定します。この値は、次のように大きな値に設定できますTimeSpan.MaxValue(特に、チャネルが信頼できるネットワークまたは vpn を介して内部で実行されている場合)。この値は、クライアントとサーバーの間に (インフラストラクチャ メッセージ以外の) アクティビティがない場合に、信頼できるセッションが「存続」する時間を定義するものです。つまり、クライアントはインターフェイスのメソッドを呼び出さず、サーバーはクライアントにコールバックしません。
  • 短い値inactivityTimeoutと大きい値を設定するとreceiveTimeout、クライアントとサーバーの間で操作上のアクティビティがない場合でも、信頼できるセッションが「維持」されます。短い非アクティブ タイムアウト (デフォルトの 10 分以下を維持したい) は、インフラストラクチャの "ping" メッセージを送信して TCP 接続を維持し、長い受信タイムアウトは信頼できるセッションをアクティブに保ちます。同時に、切断の場合に適切なタイムアウトを提供します。
  • 大きな値に設定inactivityTimeoutすると、Tcp 接続を維持する方法がなく、接続の整合性を検証する方法もないため、信頼できるセッションは信頼できなくなります。ユーザーが予期せず切断されたかどうかは、そのクライアントにメッセージを送信してみて、接続が失われていることがわかるまでわかりません。これが、この設定に Infinite を使用する多くの人がサービスで「Ping」メソッドを作成することに頼る理由です。これらの設定を正しく構成していれば、これはまったく不要です。
  • inactivityTimeoutそれよりも大きな値に設定すると、receiveTimeout同様に信頼性が低くなります。これはreceiveTimeout、操作メッセージによって引き続き制御されるためです。すなわち。設定を忘れてreceiveTimeoutデフォルトの 10 分のままにしておくと、ユーザーが 10 分間アイドル状態になると、接続が中止されます。
  • クライアントまたはサーバーが予期せず切断された場合 (アプリのクラッシュ、ネットワーク障害、誰かが電源コードにつまずいたなど)、反対側はすぐに気付かない場合があります。さまざまなテスト状況でさまざまなイベント ハンドラーをアタッチChannelFaultedしましたが、接続がすぐに失敗することもあれば、まったく失敗しないように見えることもあります。試行錯誤の末に発見したのは、障害が発生していないように見える場合でも、実際にはそのinactivityTimeout期限が切れた後に障害が発生するということです。(したがって、10 分に設定されている場合は、10 分後にChannelFaultedイベントが呼び出されます)。
  • 状況によっては切断をすぐに認識し、他の状況ではタイマーの期限が切れるのを待つ理由はまだわかりません。どちらの場合も、フレームワークによってスローされて処理される内部初回通信例外に気付き、接続を中止する呼び出しがあります... しかし、どういうわけかイベント ハンドラーの呼び出しが失われ、タイムアウトを待つ必要があります。私の疑いでは、これはどういうわけかスレッドに関連しています。
  • NetTcp チャネル全体で動作するようにメタデータを構成しようとすると、散発的な結果が得られました。うまくいくこともあれば、うまくいかないこともあります。メタデータが NetTcp では機能せず、メタデータに Http チャネルを使用する必要があるという多くのレポートを読んだことがありますが、実際には net.tcp:// url を使用していくつかの場面で機能し、プロキシー。次に、何かを変更して再コンパイルすると、機能しなくなります。物事を元に戻すと、再び機能しなくなります。そのため、同じポート (明らかに別のアドレス) のエンドポイントと共有される net.tcp を介してメタデータを機能させるには、どのような魔法の呪文が必要かは非常に混乱しました。
  • 同じサービスで NetTcp と Metatdata エンドポイントの両方を構成し、listenBacklog や maxConnections などの接続パラメーターにデフォルト以外の設定を指定する場合は、Metadata エンドポイントが同じ設定を使用していることも確認する必要があります。これらの設定は、標準の tcp mex バインディングからは利用できないためです。これには、設定listenBacklogmaxPendingConnectionsオンtcpTransport、およびgroupNameオンmaxOutboundConnectionsPerEndpointが含まれconnectionPoolSettingsます。
  • ReliableSession の Ordered 設定のデフォルト設定は ですTrue。これは、オフにするよりも多くのオーバーヘッドを使用します。順序付きメッセージが必要ない場合は、オフにすることをお勧めします (両側で設定する必要があります)。
  • -

まだ理解する必要がある構成:

共有 net.tcp メタデータ エンドポイントを正しく構成するにはどうすればよいですか? (機会があれば例を追加します) 現在、問題を回避するために http get url を指定しています。なぜそれが機能する場合と機能しない場合があるのか​​については、非常に一貫性がありません。Visual Studio でプロキシを生成するときに、「URI プレフィックスが認識されません」というエラーが発生し続けました。

inactivityTimeoutWCF が切断時にすぐにチャネルをフォールトし、期限切れになるのを待つことがあるのはなぜですか? どちらか一方の行動を制御/引き起こすのは何ですか?

4

0 に答える 0