クライアント側のハングの防止

クライアントがハングする方法は 2 つあります。ネットワーク接続によってサーバー要求が失われるか、サーバー自体がクラッシュする可能性があります。 既定のオプションでは、RPC は呼び出しをタイムアウトせず、クライアント スレッドは応答を永久に待機します。

これを防ぐ方法には、キープ アライブとタイムアウトの 2 つの方法があります。

TCP キープ アライブ

クライアントは、サーバーが稼働していて実行されていることを確認するために、サーバーに定期的に ping を実行するように設定できます。 ping は、 ncacn_ip_tcp および ncacn_http プロトコル シーケンスの TCP キープアライブであり、CPU 使用率とネットワーク帯域幅で効率的です。 特定のリモート プロシージャ 呼び出しでキープ アライブを有効にするには、呼び出しが開始される前に RpcMgmtSetComTimeout 関数を使用します。 この関数は、バインド ハンドルとタイムアウトを引数として受け取ります。 RpcMgmtSetComTimeout の後のこのバインド ハンドルに対するすべてのリモート プロシージャ 呼び出しでは、指定されたタイムアウトが使用されます。

RpcMgmtSetComTimeout 関数の Timeout パラメーターは、RPC ランタイムがキープ アライブをオンになるまでの待機時間を指定します。 タイムアウトは 0 ~ 10 の値で、0 は最小タイムアウト、10 は無限タイムアウト (タイムアウトなし) です。 タイムアウト自体は秒単位ではありません。 RpcMgmtSetComTimeout 関数に指定されたタイムアウト値から秒への変換は、RPC ランタイムによって行われ、実装固有です。

次の表に、Windows 2000 および Windows XP の秒への変換を示します。 今後のバージョンの Windows では、Timeout パラメーターとタイムアウト値の間のマッピングが秒単位で変更される可能性があります。

Timeout パラメーター 実際のタイムアウト (秒単位)
0 (RPC_C_BINDING_MIN_TIMEOUT) 120
1 240
2 360
3 480
4 600
5 (RPC_C_BINDING_DEFAULT_TIMEOUT) 720
6 840
7 960
8 1080
9 (RPC_C_BINDING_MAX_TIMEOUT) 1200
10 (RPC_C_BINDING_INFINITE_TIMEOUT) 無限タイムアウト

 

キープ アライブがオンになると、クライアントは 1 秒ごとに 1 つのキープアライブ パケットを送信します。 3 つ以上のキープ アライブに対するサーバーからの確認がない場合、クライアントは接続を停止状態として宣言し、リモート プロシージャ コールを失敗させます。 サーバーが指定されたタイムアウト内に応答を送信した場合、キープ アライブはオンになりません。 サーバーがキープ アライブに応答してもリモート プロシージャ コールに応答しない場合、クライアントはキープ アライブの送信を続けます。 サーバーが RPC 呼び出しに応答すると、キープ アライブはオフになります。 Windows 2000 の場合、同期 RPC 呼び出しの場合にのみキープ アライブが有効になります。 Windows XP の場合、非同期 RPC 呼び出しでもキープ アライブが有効になります。

クライアント アプリケーションがネットワークの問題にタイムリーに対応できるように、キープ アライブを最小値に設定したくなります。 そのような誘惑に慎重に配慮し、積極的な価値が保証されるかどうかに関する調査を適用する必要があります。 接続が一時的に失われるサーバーでは、接続が復元されると、多数のクライアントからのキープ アライブが大量に発生する可能性があります。 さらに、長い計算タスクには 2 分以上かかる場合があり、サーバーは役に立つ作業を実行するよりもキープ アライブに応答する CPU 時間が多くなる場合があります。 したがって、キープ アライブはモデレーションと共に使用する必要があります。 クライアントがスレッドが長期間関連付けられていることを許容できない場合は、非同期 RPC を考慮する必要があります。

他のプロトコル シーケンスでは、使用されるトランスポートに応じて、応答しないサーバーを検出するための異なるメカニズムが実装される場合があります。 ncalrpc トランスポートでは、キープ アライブは使用されません。 ncalrpc 内のすべての通信はローカルであるため、呼び出しの進行中にサーバーが応答しなくなると、クライアントの RPC ランタイムは直ちに呼び出しに失敗します。

通話タイムアウト

ネットワーク接続が失われた場合、またはサーバーがクラッシュした場合、TCP キープ アライブは問題ありません。 ただし、サーバーがユーザー モードでデッドロックした場合、TCP キープ アライブは正常に返されますが、呼び出しは返されません。 このシナリオに対処するために、Windows XP: RPC_C_OPT_CALL_TIMEOUT用に新しいランタイム オプションが追加されました。 このオプションは、サーバーに要求を送信するたびにタイマーを設定するように RPC ランタイムに指示します。 タイマーの有効期限が切れると、呼び出しは自動的に取り消され、RPC_S_CALL_CANCELLEDで完了します。 サーバーが指定された制限時間内に応答する限り、クライアントは呼び出しを取り消しません。 つまり、すべての応答が到着する期間がタイムアウト期間を超えた場合でも、サーバーからの各応答はタイムアウト期間内に受信されるため、マルチフラグメント呼び出しの完了にはタイムアウト期間を超える可能性があります。

また、呼び出しが取り消されると、サーバーは取り消しの通知を受け取りません。 そのため、サーバーは、ある時点で呼び出しを実行する可能性があり、クライアントは単にサーバーからの応答を無視します。

コール タイムアウトの最も危険な落とし穴は、短いタイムアウトを確立し、同じサーバーで呼び出しを再試行することです。 次のシナリオは、このアプローチの危険性を示しています。

容量に近い状態で動作するサーバーを想像してみてください。 これには、5 秒など、非常に短いタイムアウトを持つクライアントが多数います。 ルーターでのネットワーク接続または輻輳が一時的に失われると、サーバーの応答が数秒間失われます。 イーサネット ネットワークでは、この状況は、サーバーが別のコンピューターと共有するリンクでのアクティビティのバーストによって簡単に発生する可能性があります。 サーバーは、5 秒のタイムアウト前にすべての応答を送信することはできません。クライアントは呼び出しを取り消し、すぐに再試行します。 サーバーは、呼び出しが再試行であることを認識せず、それらを実行します。 したがって、通常の呼び出しワークロードを実行する代わりに、タイムアウトしたクライアントの数に応じて、30 ~ 50% の呼び出しが実行されます。これが容量を超え、サーバーが 5 秒以内にすべてのクライアントに応答できない場合は、別の呼び出しがサーバーに送信されます。 クライアントは同じ呼び出しを再発行し続け、サーバーは以前の呼び出しを処理して過負荷になっているため、タイムアウト内に応答できません。応答すると、クライアントはタイムアウトに達し、新しい呼び出しを発行し、応答を破棄しました。 最悪の場合、サーバーは再起動するまで回復せず、クライアントのアクセス パターンによっては、十分な数のクライアントが停止するまで回復しない可能性があります。

Note

コール タイムアウトは、 ncacn_ip_tcp および ncacn_http プロトコル シーケンスでのみ機能します。