このページは機械翻訳したものです。

オブジェクト・ストレージでのHDFSコネクタ

Hadoop Distributed File System (HDFS)のコネクタを使用すると、Oracle Cloud Infrastructure Object Storageサービスに対してApache Hadoopアプリケーションによってデータの読取りと書込みが可能になります。

このSDKおよびサンプルは、Universal Permissive License 1.0およびApache License 2.0でデュアルライセンスされています。サードパーティ・コンテンツはコード内の記述に従って別途ライセンスされます。

要件

HDFSコネクタを使用するには、次が必要です:

資格証明とパスワード

暗号化されたPEMファイルを資格証明に使用する場合、getPassword Hadoop構成メソッドを使用して構成からパスフレーズを読み取ります。getPasswordオプションは、登録されたセキュリティ・プロバイダでパスワードをチェックします。セキュリティ・プロバイダが、要求されたキーを含んでいない場合、かわりに構成ファイルからプレーン・テキスト・パスフレーズを直接読み取ります。

DNS名前参照のためのJVM TTLの構成

Java Virtual Machine (JVM)は、参照に対するDNS応答を一定時間キャッシュしますが、この時間はtime-to-live (TTL)と呼ばれます。これにより、頻繁に名前を解決する必要があるコードでの応答時間が短縮されます。

JVMは、networkaddress.cache.ttlプロパティを使用して、DNS名前参照のキャッシュ・ポリシーを指定します。値は、成功した参照をキャッシュする秒数を表す整数です。多くのJVMのデフォルト値は-1ですが、これは参照が永久にキャッシュされることを指定します。

Oracle Cloud Infrastructureのリソースが使用するDNS名は変わる可能性があるため、TTL値を60秒に変更することをお薦めします。こうすると、次のDNS問合せでリソースの新しいIPアドレスが返されるようになります。この値はグローバルに変更することも、ご使用のアプリケーションについてのみ変更することもできます:

  • JVMを使用してグローバルにすべてのアプリケーションのTTLを設定するには、$JAVA_HOME/jre/lib/security/java.securityファイルに次を追加します:

    networkaddress.cache.ttl=60
  • ご使用のアプリケーションのみのTTLを設定するには、アプリケーションの初期化コードに次を設定します:

    java.security.Security.setProperty("networkaddress.cache.ttl" , "60");

インストール

バンドルされたjarをlibおよびthird-party/libからHadoopクラスタの各ノードにコピーして、HadoopのCLASSPATHに含まれるようにします。

SDK for JavaおよびMavenアーティファクト

HDFSコネクタの構築は、Oracle Cloud Infrastructure SDK for Javaで提供されるMavenアーティファクトに依存します。アーティファクトを取得するには、SDK for Javaをダウンロードし、ローカルで構築する必要があります。その後、HDFSコネクタを構築できます。

重要

Oracleリリース・ページからダウンロードしたSDK for Javaファイルのバージョンは、HDFSコネクタのバージョンと一致する必要があります。これは、hdfs-connector/pom.xmlファイルのgroupId属性を含む依存関係タグ・ブロックで確認できます。

HDFSコネクタおよびMavenアーティファクト

HDFSコネクタは、Maven CentralおよびJCenterから入手できます。

プロジェクトでHDFSコネクタを使用するには、次のプロジェクト依存関係をインポートします。例:

<dependency>
  <groupId>com.oracle.oci.sdk</groupId>
  <artifactId>oci-hdfs-connector</artifactId>
  <!-- Replace the version below with your required version -->
  <version>2.9.2.0</version>
</dependency>

プロパティ

HDFSコネクタの次のプロパティをcore-site.xmlファイルに設定できます。BmcPropertiesのページには、オブジェクト・ストレージへの接続に関して構成できる追加のプロパティがリストされています。

プロパティ 説明 タイプ 必須
fs.oci.client.hostname

ホスト・エンドポイントのURL。

たとえば、https://www.example.comです。

文字列 はい
fs.oci.client.auth.tenantId

テナンシのOCID。

この値を取得するには、必要なキーとOCIDを参照してください。

文字列 はい
fs.oci.client.auth.userId

APIをコールするユーザーのOCID。

この値を取得するには、必要なキーとOCIDを参照してください。

文字列 はい
fs.oci.client.auth.fingerprint

使用されているキー・ペアのフィンガープリント。

この値を取得するには、必要なキーとOCIDを参照してください。

文字列

はい(カスタム・オーセンティケータを指定しない場合のみ)。

fs.oci.client.auth.pemfilepath 認証で使用される秘密キーのフルパスとファイル名。このファイルはローカル・ファイル・システム上にある必要があります。 文字列 はい(カスタム・オーセンティケータを指定しない場合のみ)。
fs.oci.client.auth.passphrase キーに使用されるパスフレーズ(キーが暗号化されている場合)。 文字列 キーが暗号化されている場合のみ
fs.oci.client.regionCodeOrId オブジェクト・ストレージ・エンドポイント名の作成に使用されるリージョン・コードまたはリージョン識別子。 文字列 いいえ
ノート

プロパティ名の後に.<bucket_name>.<namespace_name>を付けることで、プロパティ値が特定のバケットに適用されるよう指定できます。

リージョン・エンドポイントの設定

HDFSコネクタのリージョン・エンドポイントは、いくつかの方法で設定できます:

  • core-site.xmlでhostnameプロパティを指定
  • core-site.xmlでリージョン・コードまたはリージョン識別子プロパティを指定
  • ObjectStorageクライアントが、インスタンス・メタデータ・サービスを介してエンドポイントを取得できるようにする

core-site.xmlを使用したプロパティの構成

この例は、core-site.xmlファイルでプロパティを構成する方法を示します(OCIDは一部省略)。

<configuration>
...
  <property>
    <name>fs.oci.client.hostname</name>
    <value>https://objectstorage.us-ashburn-1.oraclecloud.com</value>
  </property>
  <property>
    <name>fs.oci.client.hostname.myBucket.myNamespace</name>
    <value>https://objectstorage.us-phoenix-1.oraclecloud.com</value><!-- Use Phoenix for myBucket@myNamespace -->
  </property>
  <property>
    <name>fs.oci.client.auth.tenantId</name>
    <value>ocid1.tenancy.oc1..exampleuniqueID</value> 
  </property>
  <property>
    <name>fs.oci.client.auth.userId</name>
    <value>ocid1.user.oc1..exampleuniqueID</value>
  </property>
  <property>
    <name>fs.oci.client.auth.fingerprint</name>
    <value>20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34</value>
  </property>
  <property>
    <name>fs.oci.client.auth.pemfilepath</name>
    <value>~/.oci/oci_api_key.pem</value>
  </property>
...
</configuration>

認証でのインスタンス・プリンシパルの使用

Oracleではインスタンス・プリンシパルが用意されており、インスタンスで実行されているサービスに対して、ユーザー資格証明を構成したりPEMファイルを指定したりする必要がなくなります。これらの各インスタンスには独自のアイデンティティがあり、インスタンス・プリンシパルによってインスタンスに追加された証明書を使用して認証されます。

HDFSコネクタでインスタンス・プリンシパル認証を使用するには、プロパティfs.oci.client.custom.authenticatorを指定して、値をcom.oracle.bmc.hdfs.auth.InstancePrincipalsCustomAuthenticatorに設定するだけです。

インスタンス・プリンシパルを使用すると、コネクタにカスタム・オーセンティケータが提供されるため、次のプロパティを構成する必要はなくなりました。

  • fs.oci.client.auth.tenantId
  • fs.oci.client.auth.userId
  • fs.oci.client.auth.fingerprint
  • fs.oci.client.auth.pemfilepath
  • fs.oci.client.auth.passphrase

次のコード例は、HDFSコネクタでの認証にインスタンス・プリンシパルを使用する方法を示しています:

<?xml version="1.0"?>
<configuration>
  <property>
    <name>fs.oci.client.hostname</name>
    <value>https://objectstorage.us-phoenix-1.oraclecloud.com</value>
  </property>
  <property>
    <name>fs.oci.client.custom.authenticator</name>
    <value>com.oracle.bmc.hdfs.auth.InstancePrincipalsCustomAuthenticator</value>
  </property>
</configuration>

インスタンス・プリンシパルの詳細は、Identity and Access Managementのためのインスタンス・プリンシパルのお知らせを参照してください。

認証でのリソース・プリンシパルの使用

Oracleでは、インスタンス・プリンシパルと同様に、インスタンスではないリソース(jupyterノートブックなど)を認証するためのリソース・プリンシパルを提供しています。各リソースには、それぞれのアイデンティティがあり、追加された証明書を使用して認証を行います。

HDFSコネクタでは、プロパティfs.oci.client.custom.authenticatorを指定して、値をcom.oracle.bmc.hdfs.auth.ResourcePrincipalsCustomAuthenticatorに設定するだけで、リソース・プリンシパル認証を使用できます。

リソース・プリンシパルを使用すると、コネクタにカスタム・オーセンティケータが提供されるため、次のプロパティを構成する必要はありません。

  • fs.oci.client.auth.tenantId
  • fs.oci.client.auth.userId
  • fs.oci.client.auth.fingerprint
  • fs.oci.client.auth.pemfilepath
  • fs.oci.client.auth.passphrase

次のサンプル・コードでは、HDFSコネクタでの認証にリソース・プリンシパルを使用する方法を示しています:

<?xml version="1.0"?>
<configuration>
  <property>
    <name>fs.oci.client.hostname</name>
    <value>https://objectstorage.us-phoenix-1.oraclecloud.com</value>
  </property>
  <property>
    <name>fs.oci.client.custom.authenticator</name>
    <value>com.oracle.bmc.hdfs.auth.ResourcePrincipalsCustomAuthenticator</value>
  </property>
</configuration>

インスタンス・プリンシパルの詳細は、データ・サイエンス・サービスでのリソース・プリンシパルの使用を参照してください。

Kerberos認証の使用

Oracleでは、HDFS Connectorを使用してオブジェクト・ストレージに接続するためのKerberos認証がサポートされています。

HDFS ConnectorでKerberos認証を使用するには:
  1. core-site.xmlで、fs.oci.client.custom.authenticatorプロパティをcom.oracle.bmc.hdfs.auth.spnego.UPSTAuthenticationCustomAuthenticatorに設定します。
  2. core-site.xmlで、次のプロパティを設定します。
    • fs.oci.client.upst.domainUrl
    • fs.oci.client.upst.clientId

    • fs.oci.client.upst.clientSecret

    • fs.oci.client.upst.tokenExchangeServicePrincipal

    • fs.oci.client.upst.userPrincipal

    • fs.oci.client.upst.issuer
    • fs.oci.client.keytab.path
    • fs.oci.client.kinit.internal.mode

次のcore-site.xmlファイルの例は、HDFS ConnectorでのSPNEGOトークン認証でのKerberosの使用を示しています。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>fs.oci.client.hostname</name>
    <value>https://objectstorage.us-phoenix-1.oraclecloud.com</value>
  </property>
  <property>
    <name>fs.oci.client.auth.tenantId</name>
    <value></value>
  </property>
  <property>
    <name>fs.oci.client.auth.userId</name>
    <value></value>
  </property>
   <property>
    <name>fs.oci.client.custom.authenticator</name>
    <value>com.oracle.bmc.hdfs.auth.spnego.UPSTAuthenticationCustomAuthenticator</value>
  </property>
  <property>
    <name>fs.oci.client.upst.tokenExchangeServicePrincipal</name>
    <value><!-- Service Principal for generating SPNEGO token --></value>
  </property>
  <property>
    <name>fs.oci.client.upst.userPrincipal</name>
    <value><!-- User Principal for generating SPNEGO token --></value>
  </property>
  <property>
    <name>fs.oci.client.upst.issuer</name>
    <value><!-- Issuer for generating SPNEGO token --></value>
  </property>
  <property>
    <name>fs.oci.client.upst.domainUrl</name>
    <value><!-- Domain application client ID for IAM token exchange --></value>
  </property>
  <property>
    <name>fs.oci.client.upst.clientId</name>
    <value><!-- Domain application client ID for IAM token exchange --></value>
  </property>
  <property>
    <name>fs.oci.client.upst.clientSecret</name>
    <value><!-- Domain application client secret for IAM token exchange --></value>
  </property>
  <property>
    <name>fs.oci.client.keytab.path</name>
    <value><!-- File path to the keytab used for token exchange --></value>
  </property>
 </configuration>

Kerberosの詳細は、Kerberosプロトコルのチュートリアルを参照してください。

SPNEGOの詳細は、RFC 4178を参照してください。

JerseyのデフォルトであるHttpUrlConnectorProviderの使用

バージョン3.3.0.7.0.0以降、HDFSでは、OCIサービス・コールを実行するために、デフォルトでApacheクライアントの使用がサポートされています。これは、HDFSコネクタがSDK for Javaに依存してサーバーにリクエストを送信するためです。SDK for Javaでは、Jersey HttpUrlConnectorProviderではなく、Jersey ApacheConnectorProviderの使用がデフォルトでサポートされており、Apache HttpClientによるOCIサービス・コールの実行が可能になっています。

Jerseyの以前のデフォルト・クライアントに切り替えるには、core-site.xmlファイルのプロパティfs.oci.client.jersey.default.connector.enabledtrueに設定します。デフォルトでは、この値はfalseに設定されています。

HDFS用のApacheコネクタを使用したパフォーマンスの最適化

Apacheコネクタでは、ApacheConnectionClosingStrategy.GracefulClosingStrategyApacheConnectionClosingStrategy.ImmediateClosingStrategyの2つ戦略で接続を切断できます。

ApacheConnectionClosingStrategy.GracefulClosingStrategyを使用すると、レスポンスから返されたストリームは、ストリームを終了するときにストリームの最後まで読み取られます。このため、残りのストリームの大きさによっては、部分読取りが行われるストリームを終了するときに、別途時間がかかる可能性があります。この遅延を回避するため、部分読取りが行われる大規模ファイルでは、ApacheConnectionClosingStrategy.ImmediateClosingStrategyの使用を検討してください。ApacheConnectionClosingStrategy.ImmediateClosingStrategyでは、ストリームを終了するときにストリームは最後まで読み取られないため、パフォーマンスが向上します。小規模なストリーム・サイズ(1MB未満のストリーム)で部分読取りを使用する場合は、ApacheConnectionClosingStrategy.ImmediateClosingStrategyに時間がかかることに注意してください。

接続の切断戦略の設定

接続の切断戦略を設定するには、core-site.xmlファイルのfs.oci.client.apache.connection.closing.strategyプロパティを設定します:

  • ApacheConnectionClosingStrategy.GracefulClosingStrategyを使用するには、fs.oci.client.apache.connection.closing.strategygracefulに設定します。
  • ApacheConnectionClosingStrategy.ImmediateClosingStrategyを使用するには、fs.oci.client.apache.connection.closing.strategyimmediateに設定します。
ノート

これらの切断方法は、HDFS用のApacheコネクタでのみ機能し、Jerseyのデフォルト・コネクタを使用する場合は無視されます。

Jerseyのデフォルト・コネクタへの切替え

Jerseyのデフォルト・コネクタでは、ストリームを最後まで読み取って再利用するため、一部のシナリオでは、HDFS用のApacheコネクタよりもパフォーマンスが向上します。Apache接続のこれらの切断方法で、お客様のユース・ケースが最適な結果にならない場合は、JerseyのデフォルトであるHttpUrlConnectorProviderに切り替えられます。Jerseyの以前のデフォルト・クライアントに切り替えるには、core-site.xmlファイルのfs.oci.client.jersey.default.connector.enabledプロパティをtrueに設定します。デフォルトでは、この値はfalseに設定されています。

詳細は、https://github.com/oracle/oci-java-sdk/blob/master/ApacheConnector-README.mdを参照してください。

HDFSでの接続プーリング

HDFSコネクタ接続プールの最大接続数を設定できます。

これを行うには、core-site.xmlファイルのプロパティfs.oci.client.apache.max.connection.pool.sizeを、プールする接続数を指定する正の整数に変更します。

ノート

このプロパティは、HDFS用のApacheConnectorを使用している場合にのみサポートされ、それ以外の場合は無視されます。

専用エンドポイント

専用エンドポイントは、クライアント・レベルで特定のレルムのサービスによって定義されるエンドポイント・テンプレートです。OCI HDFS Connectorでは、core-site.xmlでホスト名fs.oci.client.hostnameまたはエンドポイント・テンプレート・フラグfs.oci.realmspecific.endpoint.template.enabledプロパティを設定することで、これらのレルム固有のエンドポイント・テンプレートの使用を有効にできます。
ノート

エンドポイント・テンプレート・プロパティを設定する場合は、core-site.xmlfs.oci.client.regionCodeOrIdも設定する必要があります。
ノート

core-site.xmlのホスト名を使用して設定された値は、core-site.xmlのエンドポイント・テンプレート・プロパティを使用して設定された値よりも優先されます。
次の例は、fs.oci.client.hostnameプロパティを設定してレルム固有のエンドポイント・テンプレート機能を有効にする方法を示しています。
<property>
  <name>fs.oci.client.hostname</name>
  <value>https://my-namespace.objectstorage.me-dubai-1.oci.customer-oci.com</value>
</property>
次の例は、fs.oci.realmspecific.endpoint.template.enabledプロパティを設定してレルム固有のエンドポイント・テンプレート機能を有効にする方法を示しています。
<property>
  <name>fs.oci.client.regionCodeOrId</name>
  <value>me-dubai-1</value>
</property>
<property>
  <name>fs.oci.realmspecific.endpoint.template.enabled</name>
  <value>true</value>
</property>

HTTPプロキシの構成

core-site.xmlファイルに次のオプションのプロパティを設定して、HTTPプロキシを構成できます:

プロパティ 説明 タイプ 必須
fs.oci.client.proxy.uri

プロキシ・エンドポイントのURI。

たとえば、http://proxy.mydomain.com:80です。

文字列 いいえ
fs.oci.client.proxy.username プロキシで認証するユーザー名。 文字列 いいえ
fs.oci.client.proxy.password プロキシで認証するパスワード。 文字列 いいえ
fs.oci.client.multipart.allowed アップロード・マネージャがマルチパート・アップロードをサポートできるようになります ブール型 いいえ
fs.oci.client.multipart.minobjectsize.mb

アップロード・マネージャを使用するための最小オブジェクト・サイズ(MB)を指定します。

整数 いいえ
fs.oci.client.multipart.partsize.mb アップロード・マネージャのパート・サイズ(MB)を指定します。 整数 いいえ
ノート

プロキシを構成すると、オブジェクト・ストレージに接続するときにApacheConnectorProviderを使用できるようになります。これはリクエストをメモリーにバッファするため、ラージ・オブジェクトをアップロードする際のメモリー使用率に影響が生じることがあります。マルチパート・アップロードを有効にし、マルチパートのプロパティを調整して、メモリー消費を管理することをお薦めします。

ラージ・オブジェクトのアップロード

ラージ・オブジェクトは、マルチパート・アップロードを使用してオブジェクト・ストレージにアップロードされます。ファイルが小さなパートに分割されて、並列でアップロードされるため、アップロード時間が短縮されます。このため、HDFSコネクタでは、アップロード全体が失敗することがなくなり、失敗したパートのアップロードを再試行することもできます。ただし、アップロードが一時的に失敗する場合があり、コネクタは部分的にアップロードされたファイルを中止しようとします。このようなファイルは蓄積(また、格納に対して課金)されるため、定期的にアップロードをリスト表示し、一定の日数が経過したものはSDK for Javaを使用して手動で中止します。

マルチパート・アップロードを管理するためのオブジェクト・ストレージAPIの使用の方の詳細は、マルチパート・アップロードの使用を参照してください。

ノート

マルチパート・ロードの使用を望まない場合は、fs.oci.client.multipart.allowedプロパティをfalseに設定して無効にすることができます。

ベスト・プラクティス

次の各項では、使用状況とパフォーマンスを最適化するベスト・プラクティスについて説明します。

ディレクトリ名

オブジェクト・ストレージに実際のディレクトリはありません。ディレクトリのグループ分けは命名規則として機能し、オブジェクトの名前で/デリミタが使用されます。たとえば、オブジェクト名がa/example.jsonであれば、aという名前のディレクトリがあることを意味します。ただし、このオブジェクトを削除すると、aディレクトリも暗黙的に削除されます。ファイル・システムのセマンティクス(ファイルがまったく存在しなくてもディレクトリが存在できる)を維持するため、HDFSコネクタは、パスがそのディレクトリを表し、名前が/で終わる実際のオブジェクトを作成します(つまり、a/という名前のオブジェクトを作成します)。これで、a/example.jsonを削除してもaディレクトリの存在には影響しません。a/オブジェクトの存在は維持されているためです。ただし、誰かが下位のファイル/ディレクトリを削除せずにa/オブジェクトを削除する可能性は大いにあります。HDFSコネクタによって、フォルダ・オブジェクトが削除されるのは、そのパスの下位にオブジェクトがない場合のみです。フォルダ・オブジェクト自体は0バイトです。

整合性のないファイル・システム

ディレクトリの削除とは、そのディレクトリを表す接頭辞で始まるすべてのオブジェクトを削除することを意味します。HDFSでは、ファイルまたはディレクトリのファイル・ステータスを問い合せることができます。ディレクトリのファイル・ステータスは、そのディレクトリのフォルダ・オブジェクトが存在するかどうかを確認することで実装されます。ただし、フォルダ・オブジェクトが削除されても、その接頭辞が付いたいくつかのオブジェクトがまだ存在している可能性があります。たとえば、次のようなオブジェクトがある状況です:

  • a/b/example.json
  • a/b/file.json
  • a/b/

HDFSは、ディレクトリ/a/b/が存在し、それがディレクトリであることを認識しています。このディレクトリをスキャンすると、example.jsonfile.jsonが見つかります。ただし、オブジェクトa/b/が削除された場合、ファイル・システムが整合性のない状態になります。ディレクトリ/a/b/内のすべてのファイルを問い合せると、2つのエントリが見つかりますが、実際の/a/b/ディレクトリのステータスを問い合せると例外が発生します。このディレクトリは存在していないためです。HDFSコネクタが、ファイル・システムのこの状態を修正しようとすることはありません。

ファイルの作成

オブジェクト・ストレージでは、サイズがギガバイトのオブジェクトがサポートされます。通常、ファイルの作成は、一時ファイルに書き込んでから、ストリームが終了したときにファイルの内容をアップロードすることで行われます。一時領域は、複数のアップロードを処理できるだけの大きさにする必要があります。使用される一時ディレクトリは、hadoop.tmp.dir構成プロパティによって制御されます。

読取り/シークのサポート

インメモリー・バッファが有効の場合(fs.oci.io.read.inmemory)、ファイル全体がバイト配列にバッファリングされるため、シークが完全にサポートされます。インメモリー・バッファが使用可能でない場合(オブジェクト・サイズが大きい場合など)、ストリームを終了し、指定されたオフセットで始まる新しい範囲リクエストを作成することで、シークが実装されます。

ディレクトリのリスト表示

ディレクトリのリスト表示は、基本的には、接頭辞とデリミタを指定したバケットのリスト表示操作です。各キーのHDFS FileStatusインスタンスを作成するには、コネクタが追加のHEADリクエストを実行し、個々のキーのObjectMetadataを取得します。これは、オブジェクト・ストレージによってより豊富なリスト操作データがサポートされるようになるまです。

ファイル・システムおよびファイルのURIフォーマット

HDFSのファイル・システムおよびファイルは、URIを介して参照されます。スキームによりファイル・システムのタイプが指定されます。URIのその他の部分は、ファイル・システムの実装が必要に応じて自由に解釈できます。

オブジェクト・ストレージはオブジェクト・ストアであるため、オブジェクトがファイルシステム内のファイルであるかのように命名する機能を利用して、実際のファイル・システムの模倣できます。

ルート

オブジェクト・ストレージのファイル・システムのルートは、次に示すとおり、オーソリティ構成要素のバケット名とネームスペース名が含まれるパスで示されます:

ノート

この例では、MyBucketMyNamespaceはプレースホルダです。適切な値で置き換える必要があります。

oci://MyBucket@MyNamespace/
		

これは常にファイル・システムのルートです。バケットとネームスペースの両方に対してオーソリティを使用する理由は、HDFSでは、オーソリティ部分しかファイル・システムの場所を決定できないためです。パス部分には、リソースのパスのみが示されます(つまり「oci//MyNamespace/MyBucket」は機能しません)。@文字はバケットまたはネームスペースで有効な文字ではないため、オーソリティが正しく解析されることに注意してください。

サブディレクトリ

サブディレクトリは実際には存在しませんが、/文字を含むオブジェクトを作成することで模倣できます。たとえば、a/b/c/example.jsonおよびa/b/d/path.jsonという名前の2つのファイルは、共通のディレクトリa/bに存在するかのように見えます。これは、オブジェクト・ストレージの接頭辞とデリミタに基づいた問合せを使用して実現します。例で、URIとしてサブディレクトリを参照すると、次のようになります:


oci://MyBucket@MyNamespace/a/b/
		

オブジェクト/ ファイル

a/b/c/example.jsonという名前のオブジェクトは、次のように参照されます:


oci://MyBucket@MyNamespace/a/b/c/example.json
		

ロギング

コネクタのロギングは、SLF4Jを使用して行われます。SLF4Jは、ユーザー指定のロギング・ライブラリ(log4jなど)を使用できるするロギング抽象化機能です。詳細は、SLF4Jのマニュアルを参照してください。

次の例では、標準出力への基本ロギングを有効にする方法を示します。

  1. SLF4J Simple Binding jarをダウンロードします: SLF4J Simple Binding
  2. jarをクラス・パスに追加します
  3. 次のVM引数を追加して、debugレベル・ロギングを有効にします(デフォルトではinfoレベルが使用されます): -Dorg.slf4j.simpleLogger.defaultLogLevel=debug

log4jバインディングを使用すると、より高度なロギング・オプションを構成できます。

モニタリング・フレームワークの使用

HDFS Connector for Object Storageには、コネクタを使用して実行される操作に関するメトリックを提供する監視フレームワークが含まれています。モニタリング・フレームワークは、コネクタによって生成されたメトリックを消費/リスニングするために実装できるインタフェースを提供します。このインタフェースのカスタム実装を提供することも、このフレームワークに付属するOCIパブリック・テレメトリ実装を使用することもできます。

はじめに

HDFS Connectorモニタリング・フレームワークの使用を開始するには、次のプロパティを設定する必要があります。これらのプロパティをOCIMonitoringに設定したら、OCIコンソールのメトリック・エクスプローラ・ビューを使用して、HDFSコネクタから生成されたメトリックを確認できます。

fs.oci.mon.consumer.plugins

fs.oci.mon.consumer.pluginsは、モニタリング・インタフェースの実装の完全修飾クラス名のカンマ区切りリストを取得します。メトリックをOCIパブリック・テレメトリに出力する場合は、リスト内でcom.oracle.bmc.hdfs.monitoring.OCIMonitorPluginを使用する必要があります。
<property>
    <name>fs.oci.mon.consumer.plugins</name>
    <value>com.oracle.bmc.hdfs.monitoring.OCIMonitorPlugin,com.your.new.plugin.PluginImpl1</value>
</property>

fs.oci.mon.grouping.cluster.id

fs.oci.mon.grouping.cluster.idプロパティは、HDFSクラスタの識別子、またはメトリックをグループ化するその他のIDを指定します。これは必須プロパティであり、メトリックにタグ付けするためにOCIMonitorPluginでも使用されます。このプロパティは、OCIパブリック・テレメトリ・ユーザー・インタフェースおよびAPIでディメンションとして表示されます。
<property>
    <name>fs.oci.mon.grouping.cluster.id</name>
    <value>hdfs-sample-cluster-id</value>
</property>

com.oracle.bmc.hdfs.monitoring.OCIMonitorPluginプロパティ

com.oracle.bmc.hdfs.monitoring.OCIMonitorPluginプロパティが有効になっている場合、次のプロパティを適用できます。

fs.oci.mon.telemetry.ingestion.endpoint

fs.oci.mon.telemetry.ingestion.endpointプロパティは、OCIモニタリングのテレメトリ取込みエンドポイントの構成に役立ちます。詳細は、使用可能なポイントのリストを参照してください。
<property>
    <name>fs.oci.mon.telemetry.ingestion.endpoint</name>
    <value>https://telemetry-ingestion.us-ashburn-1.oraclecloud.com</value>
</property>

fs.oci.mon.compartment.ocid

fs.oci.mon.compartment.ocidプロパティは、メトリックがアタッチされるOCIコンパートメントを構成するために使用されます。これは通常、バケットが属するコンパートメントです。
<property>
    <name>fs.oci.mon.compartment.ocid</name>
    <value>ocid1.compartment.oc1..sample.compartment.id</value>
</property>

fs.oci.mon.bucket.level.enabled

fs.oci.mon.bucket.level.enabledプロパティは、バケット名をディメンションとして発行済メトリックに添付するかどうかを決定します。
<property>
    <name>fs.oci.mon.bucket.level.enabled</name>
    <value>true</value>
</property>

fs.oci.mon.ns.name

fs.oci.mon.ns.nameプロパティは、HDFSコネクタによって生成されるメトリックに使用されるネームスペースを制御します。ネームスペースの例として、"hdfsconnector"があります。これは、パブリック・テレメトリ内のoci_objectstorageなどの他の事前定義済ネームスペースとともに存在します。
<property>
    <name>fs.oci.mon.ns.name</name>
    <value>name.of.namespace.on.oci.telemetry</value>
</property>

fs.oci.mon.rg.name

fs.oci.mon.rg.nameプロパティは、メトリックの格納に使用されるリソース・グループ名を設定します。これは、一緒にモニターされるグループ化リソースの任意の論理名です。このリソース・グループ名は、OCIパブリック・テレメトリで以前に選択されたネームスペースの下に表示されます。
<property>
    <name>fs.oci.mon.rg.name</name>
    <value>name.of.resource.group.on.oci.telemetry</value>
</property>

メトリック用の独自のコンシューマの作成

com.oracle.bmc.hdfs.monitoring.OCIMonitorConsumerPluginインタフェースを使用するには、次の2つのメソッドを定義する必要があります。
  • accept
  • shutdown

拡張クラスには、OCIMonitorConsumerPluginクラスと同じシグネチャを持つコンストラクタが必要です。

例:
public OCIMonitorConsumerPlugin(BmcPropertyAccessor propertyAccessor, String bucketName, String monitoringGroupingID, String namespaceName);
この例では、コンシューマ・プラグインによって実装する必要がある各メソッドを示します。
/**
 * This class that has to be extended by any plugin, that wants to consume the metrics emitted by OCI HDFS connector.
 */
public abstract class OCIMonitorConsumerPlugin {
    /**
     * This method will be called on each plugin, by the OCI monitoring framework, whenever it wants to emit out a metric.
     * This method should finish as quickly as possible, so the consumer of this should ideally handover the
     * ocimetric and stage it elsewhere for processing, instead of trying to deal with it in the accept call itself.
     * @param ociMetric The metric that is being emitted by the OCI HDFS connector
     */
    public void accept(OCIMetric ociMetric);
 
    /**
     * This shutdown method will be called on the implementing plugins, whenever the JVM is shutting down.
     * It could be used to cleanup, finish pending tasks before exit.
     */
    public void shutdown();
}

OCIMetricクラスは、次の3つの方法で実装できます。

次のフィールドを含む単純なOCIMetricオブジェクト:
public class OCIMetric {
    /**
     * The time in milliseconds (epoch) when the metric was recorded.
     */
    private final long recordedTime;
    /**
     * The overall time taken by the operation to complete/error-out in milliseconds.
     */
    private final double overallTime;
    /**
     * The operation key. This will be one of {"LIST", "HEAD", "WRITE", "READ", "DELETE", "RENAME"}
     */
    private final String key;
    /**
     * The boolean error indicates whether the operation errored out.
     */
    private final boolean error;
    /**
     * The target OCI bucket where the operation was attempted to.
     */
    private final String bucketName;
}
OCIMetricを拡張し、スループットおよび転送バイトの追加フィールドを持つOCIMetricWithThroughputオブジェクトの実装。これは、READおよびWRITE操作に適用されます。
public class OCIMetricWithThroughput extends OCIMetric {
    /**
     * The throughput that was recorded for the operation in bytes/second
     */
    private final double throughput;
    /**
     * The total count of bytes that were transferred in or out.
     */
    private final double bytesTransferred;
}
OCIMetricWithThroughputを拡張するOCIMetricWithFBLatencyオブジェクトで、最初のバイト・レイテンシ・フィールドへの時間が追加されます。これはREAD操作にのみ適用されます。
public class OCIMetricWithFBLatency extends OCIMetricWithThroughput {
    /**
     * The time to first byte when a read operation was performed in milliseconds.
     */
    private final double ttfb;
}

Hadoopのサンプル・ジョブ

hadoop_sample_hdfs:


package com.oracle.oci.hadoop.example;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.oracle.oci.hdfs.BmcFilesystem;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class SampleOracleBmcHadoopJob
{
    private static final String SAMPLE_JOB_PATH = "/samplehadoopjob";
    private static final String INPUT_FILE = SAMPLE_JOB_PATH + "/input.dat";
    private static final String OUTPUT_DIR = SAMPLE_JOB_PATH + "/output";

    // non-static since this is the runner class it needs to initialize after we set the properties
    private final Logger log = LoggerFactory.getLogger(SampleOracleBmcHadoopJob.class);

    /**
     * Runner for sample hadoop job. This expects 3 args: path to configuration file, Object Store namespace, Object
     * Store bucket. To run this, you must:
     *{@code 


         * 
    Create a standard hadoop configuration file

         * 
    Create the bucket ahead of time.

         *} 


     * This runner will create a test input file in a file '/samplehadoopjob/input.dat', and job results will be written
     * to '/samplehadoopjob/output'.
     * 
     * @param args
     *            1) path to configuration file, 2) namespace, 3) bucket
     * @throws Exception
     */
    public static void main(final String[] args) throws Exception
    {
        if (args.length != 3)
        {
            throw new IllegalArgumentException(
                    "Must have 3 args: 1) path to config file, 2) object storage namespace, 3) object storage bucket");
        }

        // redirect all logs to sysout
        System.setProperty("org.slf4j.simpleLogger.logFile", "System.out");
        System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");

        final SampleOracleBmcHadoopJob job = new SampleOracleBmcHadoopJob(args[0], args[1], args[2]);
        System.exit(job.execute());
    }

    private final String configurationFilePath;
    private final String namespace;
    private final String bucket;

    public int execute() throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException
    {
        log.info("Creating hadoop configuration");
        final Configuration configuration = this.createConfiguration(this.configurationFilePath);

        final String authority = this.bucket + "@" + this.namespace;
        final String uri = "oci://" + authority;
        log.info("Using uri: {}", uri);

        log.info("Creating job inputs");
        this.setup(uri, configuration);

        log.info("Creating job");
        final Job job = this.createJob(configuration);

        final String in = uri + INPUT_FILE;
        final String out = uri + OUTPUT_DIR;
        log.info("Using input: {}", in);
        log.info("Using output: {}", out);

        FileInputFormat.addInputPath(job, new Path(in));
        FileOutputFormat.setOutputPath(job, new Path(out));

        log.info("Executing job...");
        final int response = job.waitForCompletion(true) ? 0 : 1;

        log.info("Attempting to read job results");
        this.tryReadResult(uri, configuration);
        return response;
    }

    private Configuration createConfiguration(final String configFilePath)
    {
        final Configuration configuration = new Configuration();
        configuration.addResource(new Path(configFilePath));
        return configuration;
    }

    private void setup(final String uri, final Configuration configuration) throws IOException, URISyntaxException
    {
        try (final BmcFilesystem fs = new BmcFilesystem())
        {
            fs.initialize(new URI(uri), configuration);
            fs.delete(new Path(SAMPLE_JOB_PATH), true);
            final FSDataOutputStream output = fs.create(new Path(INPUT_FILE));
            output.writeChars("example\npath\ngak\ntest\nexample\ngak\n\ngak");
            output.close();
        }
    }

    private Job createJob(final Configuration configuration) throws IOException
    {
        final Job job = Job.getInstance(configuration, "word count");
        job.setJarByClass(SampleOracleBmcHadoopJob.class);
        job.setMapperClass(SimpleMapper.class);
        job.setCombinerClass(SimpleReducer.class);
        job.setReducerClass(SimpleReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        return job;
    }

    private void tryReadResult(final String uri, final Configuration configuration)
            throws IOException, URISyntaxException
    {
        try (final BmcFilesystem fs = new BmcFilesystem())
        {
            fs.initialize(new URI(uri), configuration);
            // this should be the output file name, but that could change
            final FSDataInputStream input = fs.open(new Path(OUTPUT_DIR + "/part-r-00000"));

            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
            IOUtils.copy(input, baos);
            log.info("\n=====\n" + baos.toString() + "=====");
            input.close();
        }
    }
}


package com.oracle.oci.hadoop.example;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class SimpleMapper extends Mapper
{
    private final static IntWritable one = new IntWritable(1);
    private final Text word = new Text();

    @Override
    public void map(final Object key, final Text value, final Context context) throws IOException, InterruptedException
    {
        final StringTokenizer itr = new StringTokenizer(value.toString());
        while (itr.hasMoreTokens())
        {
            this.word.set(itr.nextToken());
            context.write(this.word, one);
        }
    }
}


package com.oracle.oci.hadoop.example;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class SimpleReducer extends Reducer
{
    private final IntWritable result = new IntWritable();

    @Override
    public void reduce(final Text key, final Iterable values, final Context context)
            throws IOException, InterruptedException
    {
        int sum = 0;
        for (final IntWritable val : values)
        {
            sum += val.get();
        }
        this.result.set(sum);
        context.write(key, this.result);
    }
}

トラブルシューティング

この項には、HDFSコネクタのトラブルシューティング情報が含まれています。

サービス・エラーのトラブルシューティング

サービス・エラーを引き起こすすべての操作は、HDFSコネクタによって例外タイプcom.oracle.bmc.model.BmcExceptionがスローされる原因となります。OCIから返される一般的なサービス・エラーの詳細は、APIエラーを参照してください。

Java暗号化キーのサイズ・エラー

HDFSコネクタで処理できるのは、キー長が128ビット以下のキーのみです。AES256などサイズが大きいキーを使用すると、「Invalid Key Exception」や「Illegal key size」のエアーを受け取ります。この問題を修正するには、次のいずれかの回避策を使用します:

通知

HDFSコネクタの新しいバージョンがリリースされたときに通知を受け取るには、Atomフィードをサブスクライブします。