Hadoopサービスレジストリの使用

Hadoopサービスレジストリは、さまざまな方法で使用できます。

  1. YARNアプリケーションのライフサイクルに合わせて、動的にデプロイされたYARNアプリケーションを登録できます。サービスレコードは、YARNアプリケーション、アプリケーション試行、または個々のコンテナの完了時に削除されるように設定できます。
  2. 静的または動的なアプリケーションと、それらと通信するメカニズムを検索します。これらのメカニズムには、HTTP(S) URL、Zookeeperパス、ホスト名とポート、さらには設定データへのHadoopファイルシステムのパスを含めることができます。
  3. セキュアクラスターでは、サービスバインディングが特定のユーザーまたはシステムアカウントによって公開されたことを確認します。これは、エントリが配置されたパスを確認するだけで実行できます。
  4. 静的アプリケーションを登録します。これらは削除されるまでレジストリに残ります。必要に応じて更新できます。

レジストリのユーザーは、エントリ(サービスレコード)のパブリッシャーと、サービスレコードを介して場所が特定された他のサービスのコンシューマーの両方になる可能性があります。分散アプリケーションの異なる部分も、異なる目的で使用する場合があります。例として、YARNアプリケーションのアプリケーションマスターは、ワーカーコンテナで使用するためにバインディングを公開できます。コンテナで実行されているコードは、クラスター内の異なるノードで再起動された場合でも、そのマネージャーと通信するためのバインディングを検索できます。クライアントアプリケーションは、パブリックAPIを介してAMと対話するための外部サービスエンドポイントを検索できます。

レジストリは次の目的では使用できません。

レジストリアプリケーションの設計パターン

パブリックサービスエンドポイントを登録する短期YARNアプリケーションマスター

  1. YARNアプリケーションがデプロイされます。セキュアクラスターでは、レジストリに書き込むためのKerberosトークンが付与されます。
  2. 起動時に、既知のパスにサービスレコードを作成します。
  3. このレコードには、アプリケーション試行の永続化ポリシーとアプリケーション試行のIDがある場合があります。
    yarn:persistence = "application_attempt"
    yarn:id = ${application_attemptId}
    

    これは、新しい試行が作成された場合でも、アプリケーション試行が完了するとレコードが削除されることを意味します。すべてのアプリケーション試行は、エンドポイントを再登録する必要があります(いずれにせよ、サービスの場所を特定する必要がある場合があります)。

  4. あるいは、レコードには「アプリケーション」の永続化ポリシーがある場合があります。
    yarn:persistence = "application_attempt"
    yarn:id = application_attemptId
    

    これは、エンドポイント情報が古い場合でも、アプリケーション試行の間でもレコードが永続化されることを意味します。

  5. クライアントアプリケーションは、パスを使用してサービスを検索します。

パスの選択は、アプリケーション固有のものです。一意であることが保証されているYARNアプリケーション名を持つサービスの場合、次の規則をお勧めします。

/users/${username}/applications/${service-class}/${instance-name}

または、アプリケーションIDをパスで使用できます。

/users/${username}/applications/${service-class}/${applicationId}

後者を使用すると、YARNアプリケーションリストのエントリをサービスレコードに簡単にマッピングできます。

クライアントアプリケーションはサービスを検索できます

  • サービスクラスのすべてのインスタンスを列挙し、特定の基準で1つを選択することによって。
  • 提供されたサービスクラスとインスタンス名から
  • アプリケーションIDでリストされている場合は、サービスクラスとアプリケーションIDから。

サービスレコードの場所を特定した後、クライアントは外部バインディングを列挙し、目的のAPIを持つエントリを見つけることができます。

パブリックサービスエンドポイントを登録するYARNコンテナ

ここでは、YARNアプリケーションのすべてのコンテナが、一般に公開するためにサービスエンドポイントを公開しています。

  1. デプロイされたコンテナには、自身を登録する必要があるベースパスが渡されます。
  2. 長期間実行されるコンテナには、ユーザーのKerberos認証情報なしにこれらのエントリを更新する権利を付与するid:passwordペアが渡される必要があります。これにより、コンテナは、AMにレジストリパスへの書き込みアクセスを許可するユーザートークンの有効期限が切れた後でも、エントリを更新できます。
  3. コンテナは、id:passwordペアを使用してレジストリ操作インスタンスをインスタンス化します。
  4. 次に、次のものからなるパスにサービスレコードを登録します。
    ${base-path} + "/" + RegistryPathUtils.encodeYarnID(containerId)
    

    このレコードには、コンテナの永続化ポリシーとコンテナのIDが必要です。

    yarn:persistence = "container"
    yarn:id = containerId
    

    コンテナが終了すると、エントリは自動的に削除されます。

  5. このコンテナデプロイサービスの公開されたサービスエンドポイントは、サービスレコードの外部エンドポイントリストにリストする必要があります。

  6. クライアントは、${base-path}の下のエントリをリストすることにより、YARNアプリケーションによってエクスポートされたすべてのコンテナを列挙できます。

静的クラスターサービスの登録

クラスターで一般的に固定されているが、バインディングと構成情報を公開する必要があるサービスは、レジストリに公開できます。例:Apache Oozieサービス。デプロイされたアプリケーションが公開できるクラスターの外部のサービス。例:Amazon Dynamoインスタンス。

これらのサービスは、/users/oozie/users/hbaseなど、サービスを実行しているユーザーに属するパスに登録できます。クライアントアプリケーションはこのパスを使用します。これにより、サービスレコードの有効性を認証できますが、クライアントアプリケーションがサービスがデプロイされているユーザー名を知っているか、完全なパスで構成されている必要があります。

別の方法は、サービスが/servicesの下の静的サービスパスにデプロイされることです。たとえば、/services/oozieにはOozieサービスの登録を含めることができます。このパスのアクセス許可は事前構成されたシステムアカウントに制限されているため、セキュアクラスター上のこのパスのサービス登録の存在は、クラスター管理ツールによって登録されたことを確認します。

  1. サービスは、何らかの管理ツールによって、またはクラスターオペレーターによって直接デプロイされます。
  2. デプロイされたアプリケーションは、レジストリのバインディング情報が指定されている場合、自身のユーザー名で自身を登録できます。
  3. アプリケーションが/servicesの下に登録される場合、システムユーザーアカウントのいずれかによってデプロイされている場合は、自身を直接登録できます。
  4. アプリケーションにそのためのアクセス許可がない場合は、クラスター管理ツールが代わりにサービスを登録する必要があります。
  5. クライアントアプリケーションは、既知/構成済みのパスを解決することでサービスを検索できます。
  6. サービスが停止した場合、管理ツールはエントリを削除するか、エントリを保持したままサービスエンドポイントをすべて削除する可能性があります。これは、「サービスは認識されているが、現在到達不能である」ことを示すための提案された規約です。
  7. サービスが再起動されると、そのバインディング情報が更新されるか、レジストリエントリ全体が再作成される可能性があります。

YARNコンテナがApplication Masterを特定する方法

ここで、YARNコンテナは、作業を受け取るためにAMに登録します。通常は、定期的にレポートするハートビートメカニズムによって行われます。AMがアプリケーションの試行よりも長くコンテナが存続するように構成されている場合、AMが失敗してもコンテナは実行を続けます。これらのコンテナは、再起動されたAMにバインドする必要があります。また、AMが再起動しない場合は、最終的にタイムアウトして自身を終了する必要があると結論付けたい場合があります。このようなポリシーは、アプリケーションがネットワークパーティションに対応するのに役立ちます。

  1. YARN AMは、IPC通信に必要なFQDNやソケットポート、またはRESTチャネルに必要なHTTP/HTTPS URLなどのサービスエンドポイントを公開します。これらは、internalエンドポイントリストに、コンテナが使用する特定のAPIのURLに設定されたapiフィールドとともに公開されます。
  2. YARNコンテナは、サービスレコードへのパスとともに(何らかの方法で)起動されます。環境変数またはコマンドラインパラメータが2つの実行可能なメカニズムです。共有シークレットも同様に渡す必要があります。コマンドラインパラメータは、unixのpsコマンドで表示できます。より安全なのは、共有シークレットをクラスターファイルシステムに保存し、そのパスをコンテナに渡すことです。そのようなパスへのURIは、アプリケーションの登録された内部エンドポイントの1つである可能性があります。
  3. YARNコンテナは、サービスレジストリを検索して通信バインディングを特定します。
  4. 登録されたサービスエントリが見つからない場合、コンテナは次のいずれかを行うことができます。終了する。エントリが再表示されるまで、いくつかの(ジッタ付きの)再試行期間でスピンし、エントリをポーリングする。これは、AMが見つかったことを意味します。
  5. サービスエントリが見つかった場合、クライアントはAMのチャネルでAMとの通信を試みる必要があります。クライアントとサーバーを相互に検証するために、共有認証の詳細を使用できます。
  6. 接続が開始できなかったり、認証に失敗したり、長期間の接続が切断されて再起動できなくなるまで、クライアントはAMにレポートします。
  7. この時点で、クライアントはステップ(3)に戻る可能性があります。繰り返しますが、ジッタを含むいくつかのバックオフポリシーは、再起動したばかりのAMが過負荷になるのを防ぐのに役立ちます。コンテナは、AMが復帰しないと結論付け、終了するまでのタイムアウトを設定することもできます。
  8. AMがクライアントに発行する可能性のある機能コマンドに加えて、「terminate」コマンドをコンテナに発行できることをお勧めします。これにより、システムは、生成されたコンテナが実行を継続している間にYARNノードマネージャーが終了するという特定の状況を処理できます。

YARNアプリケーションとコンテナが管理およびメトリクスのバインディングを公開する

管理ポートとバインディングは、公開する他のエンドポイントにすぎません。これらは、一般公開を目的としていないため、internalエンドポイントとして公開する必要があります。

クライアントアプリケーションによるエンドポイントAPIによるサービスの列挙

クライアントアプリケーションは、"classpath://org.apache.hbase"のような特定のAPIを実装するすべてのサービスを特定したいと考えています。

  1. クライアントはレジストリ内のパスから開始します。
  2. クライアントは、registryOperations.list(path)を呼び出して、そのパスの直下にあるすべてのノードをリストし、子ノードの相対リストを取得します。
  3. クライアントは、各子のstat()を呼び出して、子レコードのステータスを列挙します。
  4. すべてのステータスエントリについて、エントリのサイズがServiceRecordHeader.getLength()の値よりも大きい場合、サービスレコードが含まれている可能性があります。
  5. 内容は、resolve()操作を使用して取得できます。成功した場合、サービスレコードが含まれています。したがって、クライアントはexternalエンドポイントを列挙し、目的のAPIを持つエンドポイントを見つけることができます。
  6. RegistryPathStatusステータスエントリのchildrenフィールドを調べます。それが >= 0 の場合、そのエントリのパスで列挙を再帰的に実行する必要があります。
  7. 操作は最終的に、すべてのエントリのリストで完了します。
  8. 列挙されたエンドポイントの1つを選択し、サービスのバインディング情報として使用できます。

このアルゴリズムは、レジストリツリーの深さ優先探索を記述しています。もちろん、幅優先探索や、単一のエントリポイントが見つかるとすぐに検索を停止するなど、バリエーションも可能です。また、異なるサブツリーの並列検索というオプションもあります。これにより検索時間を短縮できますが、レジストリインフラストラクチャに対するクライアントの負荷が高くなります。

ユーティリティクラスRegistryUtilsは、共通のレジストリ操作用の静的ユーティリティメソッドを提供します。特に、RegistryUtils.listServiceRecords(registryOperations, path)は、指定されたパスのすべての子レコードエントリのリストと収集を実行します。

クライアントアプリケーションは、「エンドポイントが無効な場合」、具体的には、サービスが実行されていない場合はどうするかという問題に直面します。

一部のトランスポートは、停止は一時的なものであり、元のバインディングに対してスピン再試行を行うことが正しい戦略であると想定しています。これは、Hadoop IPCクライアントのデフォルトポリシーです。

他のトランスポートは、例外やその他のメカニズムを介して、失敗をすぐに報告します。これはクライアントに直接表示されますが、クライアントがレジストリを再スキャンしてアプリケーションに再バインドできます。

最後に、一部のアプリケーションは当初から動的なフェイルオーバー用に設計されています。公開されているバインディング情報は、実際にはzookeeperパスです。Apache HBaseとApache Accumuloがその例です。レジストリはバインディングの最初のルックアップに使用され、その後クライアントは本質的に障害に対して回復力があります。