このドキュメントでは、Hadoopのフェアコールキューを構成および管理する方法について説明します。
Hadoopが正しくインストール、構成、およびセットアップされていることを確認してください。 詳細については、以下を参照してください。
Hadoopサーバーコンポーネント、特にHDFS NameNodeは、クライアントから非常に重いRPC負荷を受けます。 デフォルトでは、すべてのクライアントリクエストは先入れ先出しキューを介してルーティングされ、到着順に処理されます。 つまり、非常に多数のリクエストを送信する単一のユーザーがサービスを簡単に圧倒し、他のすべてのユーザーのサービスを低下させる可能性があります。 フェアコールキューと関連コンポーネントは、この影響を軽減することを目的としています。
IPCスタックには、それぞれ独自のパラメータを持つ複雑な相互作用を持つコンポーネントがいくつかあります。 下の図は、それらの相互作用の概略図を示しており、以下で説明します。
以下の説明では、**太字**は名前付きエンティティまたは構成可能要素を表します。
クライアントがIPCサーバーにリクエストを行うと、このリクエストは最初に**リスンキュー**に送られます。 **リーダー**スレッドはこのキューからリクエストを削除し、構成可能な**RpcScheduler**に渡して優先順位を割り当て、**コールキュー**に配置します。 これは、FairCallQueueがプラグイン可能な実装として配置される場所です(他の既存の実装はFIFOキューです)。 **ハンドラ**スレッドはコールキューからリクエストを受け入れ、処理し、クライアントに応答します。
デフォルトでFairCallQueueで使用されるRpcSchedulerの実装は**DecayRpcScheduler**であり、これは各ユーザーが受信したリクエストの数を保持します。 このカウントは時間とともに**減衰**します。 **スイープ期間**(デフォルトでは5秒)ごとに、ユーザーあたりのリクエスト数は**減衰係数**(デフォルトでは0.5)で乗算されます。 これにより、ユーザーあたりのリクエスト数の加重/移動平均が維持されます。 スイープが実行されるたびに、既知のすべてのユーザーのコールカウントが最高から最低にランク付けされます。 各ユーザーには、そのユーザーからのコールの割合に基づいて**優先順位**(デフォルトでは0〜3、0が最高の優先順位)が割り当てられます。 デフォルトの**優先順位しきい値**は(0.125、0.25、0.5)です。つまり、コールが全体の50%以上を占めるユーザー(そのようなユーザーは最大1人)は最低の優先順位に配置され、コールが全体の25%から50%を占めるユーザーは2番目に低い優先順位に配置されます。 コールが12.5%から25%を占めるユーザーは2番目に高い優先順位に配置され、他のすべてのユーザーは最高の優先順位に配置されます。 スイープの最後に、既知の各ユーザーには、次のスイープまで使用されるキャッシュされた優先順位があります。 スイープの間に現れる新しいユーザーは、その場で優先順位が計算されます。
FairCallQueue内には、それぞれに**重み**が指定された複数の**優先順位キュー**があります。 リクエストがコールキューに到着すると、リクエストは、コールに割り当てられた現在の優先順位(RpcSchedulerによる)に基づいて、これらの優先順位キューのいずれかに配置されます。 ハンドラスレッドがコールキューからアイテムを取得しようとすると、どのキューからプルするかは**RpcMultiplexer**によって決定されます。 現在、これは**WeightedRoundRobinMultiplexer**にハードコードされています。 WRRMは、キューの重みに基づいてリクエストを処理します。 デフォルトの4つの優先順位レベルのデフォルトの重みは(8、4、2、1)です。 したがって、WRRMは、最高の優先順位キューから8つのリクエスト、2番目に高いキューから4つ、3番目に高いキューから2つ、最低のキューから1つを処理し、次に最高の優先順位キューからさらに8つを処理します。
上記の優先順位付けメカニズムに加えて、構成可能な**バックオフ**メカニズムもあります。このメカニズムでは、サーバーはリクエストを処理するのではなく、クライアントに例外をスローします。 クライアントは、再試行する前にしばらく待つこと(つまり、指数バックオフを介して)が想定されています。 通常、バックオフは、キューがいっぱいになったときに優先順位キュー(FCQの)にリクエストを配置しようとするとトリガーされます。 これは、影響の大きいクライアントをさらに押し戻し、負荷を削減するのに役立ち、大きなメリットをもたらす可能性があります。 また、**応答時間によるバックオフ**という機能もあり、優先順位の高いレベルのリクエストの処理が遅すぎる場合、優先順位の低いレベルのリクエストがバックオフされます。 たとえば、優先順位1の応答時間しきい値が10秒に設定されているが、そのキューの平均応答時間が12秒である場合、優先順位レベル2以下の着信リクエストはバックオフ例外を受け取りますが、優先順位レベル0および1のリクエストは通常どおり処理されます。 目的は、システム全体の負荷が大きすぎて優先順位の高いクライアントに影響を与える場合、負荷の高いクライアントを強制的にバックオフさせることです。
上記の説明では、調整のためにリクエストをグループ化する方法について説明する際に、リクエストの**ユーザー**について言及しています。 これは、デフォルトで**UserIdentityProvider**である**IDプロバイダー**を介して構成可能です。 ユーザーIDプロバイダーは、リクエストを送信するクライアントのユーザー名を使用するだけです。 ただし、カスタムIDプロバイダーを使用して、他のグループ化に基づいて調整を実行したり、外部IDプロバイダーを使用したりできます。
フェアコールキュー自体は、非常に多くのリクエストを送信するユーザーからの影響を軽減するのに役立ちますが、各リクエストの処理にかかるコストは考慮していません。 したがって、HDFS NameNodeを検討する場合、1000個の「getFileInfo」リクエストを送信するユーザーは、非常に大きなディレクトリに1000個の「listStatus」リクエストを送信するユーザー、またはネームシステムの排他ロックを必要とするため、より高価な1000個の「mkdir」リクエストを送信するユーザーと同じ優先順位が付けられます。 ユーザーリクエストの優先順位付けを検討する際に操作の**コスト**を考慮に入れるために、ユーザーの操作の合計処理時間を使用して、そのユーザーの優先順位を決定する方法を決定する、フェアコールキューの「コストベース」の拡張機能があります。 デフォルトでは、キュー時間(処理されるまで待機する時間)とロック待機時間(ロックを取得するまで待機する時間)はコストに含まれず、ロックなしで処理に費やされた時間はニュートラル(1倍)に重み付けされ、共有ロックで処理に費やされた時間は10倍高く重み付けされ、排他ロックで処理に費やされた時間は100倍高く重み付けされます。 これは、サーバーに配置された実際の負荷に基づいてユーザーの優先順位を付けることを試みます。 この機能を有効にするには、以下で説明するように、`costprovder.impl`構成を`org.apache.hadoop.ipc.WeightedTimeCostProvider`に設定します。
このセクションでは、フェアコールキューを構成する方法について説明します。
すべてのコールキュー関連の構成は、単一のIPCサーバーのみに関連します。 これにより、単一の構成ファイルを使用して、異なるコンポーネント、またはコンポーネント内の異なるIPCサーバーでさえ、個別に構成されたコールキューを持つように構成できます。 各構成には、`ipc.<port_number>`というプレフィックスが付きます。ここで、`<port_number>`は、構成されるIPCサーバーが使用するポートです。 たとえば、`ipc.8020.callqueue.impl`は、ポート8020で実行されているIPCサーバーのコールキュー実装を調整します。 このセクションの残りの部分では、このプレフィックスは省略されます。
構成キー | 該当コンポーネント | 説明 | デフォルト |
---|---|---|---|
backoff.enable | 全般 | キューがいっぱいになったときにクライアントのバックオフを有効にするかどうか。 | false |
callqueue.impl | 全般 | 呼び出しキューの実装として使用するクラスの完全修飾名。Fair Call Queueにはorg.apache.hadoop.ipc.FairCallQueue を使用します。 |
java.util.concurrent.LinkedBlockingQueue (FIFOキュー) |
scheduler.impl | 全般 | スケジューラの実装として使用するクラスの完全修飾名。Fair Call Queueと組み合わせてorg.apache.hadoop.ipc.DecayRpcScheduler を使用します。 |
org.apache.hadoop.ipc.DefaultRpcScheduler (no-opスケジューラ)FairCallQueueを使用する場合、デフォルトは org.apache.hadoop.ipc.DecayRpcScheduler です。 |
scheduler.priority.levels | RpcScheduler, CallQueue | スケジューラと呼び出しキュー内で使用する優先順位レベルの数。 | 4 |
faircallqueue.multiplexer.weights | WeightedRoundRobinMultiplexer | 各優先順位キューに与える重み。これは、優先順位レベルの数に等しい長さのカンマ区切りリストである必要があります。 | 重みは2の倍数で降順に設定します(例:4レベルの場合:8,4,2,1 ) |
identity-provider.impl | DecayRpcScheduler | ユーザーリクエストをそのIDにマッピングするIDプロバイダー。 | org.apache.hadoop.ipc.UserIdentityProvider |
cost-provider.impl | DecayRpcScheduler | ユーザーリクエストをそのコストにマッピングするコストプロバイダー。処理時間に基づいてコストを決定するには、org.apache.hadoop.ipc.WeightedTimeCostProvider を使用します。 |
org.apache.hadoop.ipc.DefaultCostProvider |
decay-scheduler.period-ms | DecayRpcScheduler | ユーザーの操作カウントに減衰係数を適用する頻度。値が大きいほどオーバーヘッドは少なくなりますが、クライアントの動作の変化への応答速度は遅くなります。 | 5000 |
decay-scheduler.decay-factor | DecayRpcScheduler | ユーザーの操作カウントを減衰させる際に適用する乗法的な減衰係数。値が大きいほど、古い操作の重みが大きくなり、スケジューラのメモリが長くなり、負荷の高いクライアントがより長い期間ペナルティを受けます。 | 0.5 |
decay-scheduler.thresholds | DecayRpcScheduler | 各優先順位キューのクライアント負荷しきい値(整数パーセンテージ)。位置iで指定されたよりも操作の合計に対する負荷の割合が低いクライアントには、優先順位iが与えられます。これは、優先順位レベルの数から1を引いた長さのカンマ区切りリストである必要があります(最後は暗黙的に100です)。 | しきい値は2の倍数で昇順に設定します(例:4レベルの場合:13,25,50 ) |
decay-scheduler.backoff.responsetime.enable | DecayRpcScheduler | 応答時間によるバックオフ機能を有効にするかどうか。 | false |
decay-scheduler.backoff.responsetime.thresholds | DecayRpcScheduler | 各優先順位キューの応答時間しきい値(時間)。キューの平均応答時間がこのしきい値を超えると、優先順位の低いキューでバックオフが発生します。これは、優先順位レベルの数に等しい長さのカンマ区切りリストである必要があります。 | しきい値はレベルごとに10秒増加します(例:4レベルの場合:10s,20s,30s,40s ) |
decay-scheduler.metrics.top.user.count | DecayRpcScheduler | メトリック情報を送信する上位(つまり、最も負荷の高い)ユーザーの数。 | 10 |
weighted-cost.lockshared | WeightedTimeCostProvider | 共有(読み取り)ロックを保持する処理フェーズで費やされた時間に適用する重み乗数。 | 10 |
weighted-cost.lockexclusive | WeightedTimeCostProvider | 排他(書き込み)ロックを保持する処理フェーズで費やされた時間に適用する重み乗数。 | 100 |
weighted-cost.{handler,lockfree,response} | WeightedTimeCostProvider | ロックの保持を伴わない処理フェーズで費やされた時間に適用する重み乗数。各フェーズの詳細については、org.apache.hadoop.ipc.ProcessingDetails.Timing を参照してください。 |
1 |
これは、ポート8020のIPCサーバーがFairCallQueue
とDecayRpcScheduler
を使用し、優先順位レベルが2つだけになるように設定する例です。上位10%のユーザーは、処理されるリクエスト全体の1%しか割り当てられないため、大きなペナルティが課せられます。
<property> <name>ipc.8020.callqueue.impl</name> <value>org.apache.hadoop.ipc.FairCallQueue</value> </property> <property> <name>ipc.8020.scheduler.impl</name> <value>org.apache.hadoop.ipc.DecayRpcScheduler</value> </property> <property> <name>ipc.8020.scheduler.priority.levels</name> <value>2</value> </property> <property> <name>ipc.8020.faircallqueue.multiplexer.weights</name> <value>99,1</value> </property> <property> <name>ipc.8020.decay-scheduler.thresholds</name> <value>90</value> </property>