S3は、Amazon EC2上で実行される仮想クラスタであっても、HDFSよりも処理が遅くなります。
これは、以下に示すように、非常に異なるシステムであるためです。
機能 | HDFS | S3Aコネクタを介したS3 |
---|---|---|
通信 | RPC | HTTP GET/PUT/HEAD/LIST/COPYリクエスト |
データの局所性 | ローカルストレージ | リモートS3サーバー |
レプリケーション | 複数のデータノード | アップロード後の非同期 |
整合性 | 一貫性のあるデータとリスト | 2020年11月以降一貫性がある |
帯域幅 | 最高: ローカルIO、最悪: データセンターネットワーク | サーバーとS3間の帯域幅 |
遅延 | 低 | 高い、「低コスト」ディレクトリ操作の場合 |
rename | 高速、アトミック | COPYとDELETEによる遅い偽のrename |
delete | 高速、アトミック | ファイルの場合は高速、ディレクトリの場合は遅く非アトミック |
書き込み | インクリメンタル | ブロック単位; ライターが閉じられるまで表示されない |
読み込み | seek() は高速 | seek() は低速でコストがかかる |
IOPs | ハードウェアのみによって制限される | 呼び出し元はS3バケット内のシャードにスロットリングされる |
セキュリティ | Posixユーザー+グループ; ACL | AWSロールとポリシー |
パフォーマンスの観点から、覚えておくべき重要な点は次のとおりです。
rename()
の低速なパフォーマンスは、ジョブのコミットフェーズ、DistCP
などのアプリケーション、および他の場所で表面化します。seek()
を呼び出すと、新しいHTTPリクエストが強制される可能性があります。これにより、列指向のParquet/ORCデータの読み取りが高価になる可能性があります。全体として、S3AコネクタはS3をファイルシステムのように見せますが、そうではなく、メタファーを保持しようとする試みは「著しく最適ではありません」。
S3を最も効率的に使用するには、注意が必要です。
S3Aファイルシステムは、クライアントが読み取るファイル範囲のリストを提供することで、ベクトル化された読み取りAPIの実装をサポートし、各範囲に関連付けられた将来の読み取りオブジェクトを返します。完全なAPI仕様については、FSDataInputStreamを参照してください。
クライアントの要件に基づいて、ベクトル化された読み取りを最適化するために、次のプロパティを設定できます。
<property> <name>fs.s3a.vectored.read.min.seek.size</name> <value>4K</value> <description> What is the smallest reasonable seek in bytes such that we group ranges together during vectored read operation. </description> </property> <property> <name>fs.s3a.vectored.read.max.merged.size</name> <value>1M</value> <description> What is the largest merged read size in bytes such that we group ranges together during vectored read. Setting this value to 0 will disable merging of ranges. </description> <property> <name>fs.s3a.vectored.active.ranged.reads</name> <value>4</value> <description> Maximum number of range reads a single input stream can have active (downloading, or queued) to the central FileSystem instance's pool of queued operations. This stops a single stream overloading the shared thread pool. </description> </property>
S3Aファイルシステムクライアントは、Posix fadvise()
API呼び出しと同様の入力ポリシーの概念をサポートしています。これにより、さまざまなユースケース向けにHTTP GETリクエストを最適化するために、S3Aクライアントの動作が調整されます。
sequential
ファイル全体を読み取ります。場合によっては、短い前方シークを伴います。
ドキュメント全体が単一のHTTPリクエストでリクエストされます。リードアヘッド範囲内の前方シークは、中間データをスキップすることでサポートされます。
これにより、最大のシーケンシャルスループットが実現されますが、後方シークは非常にコストがかかります。
ファイル (DistCP、コピー操作) を一括で読み取るアプリケーションは、gzip圧縮された .gz
ファイルからデータを読み取るアプリケーションと同様に、シーケンシャルアクセスを使用する必要があります。「ノーマル」fadviseポリシーはシーケンシャルIOモードで開始するため、このポリシーを明示的にリクエストする必要はめったにありません。
random
ランダムIO、特にHadoop PositionedReadable
操作向けに最適化されています。ただし、seek(offset); read(byte_buffer)
もメリットがあります。
ファイル全体を要求するのではなく、HTTPリクエストの範囲は、read
操作で必要なデータの長さに設定されます (必要に応じて、setReadahead()
で設定されたリードアヘッド値に切り上げられます)。
既存のHTTPリクエストを閉じるコストを削減することにより、これは、一連の PositionedReadable.read()
および PositionedReadable.readFully()
呼び出しを介してバイナリファイルにアクセスするファイルIOに非常に効率的です。ファイルのシーケンシャル読み取りは、ファイル全体を読み取るために多数のHTTPリクエストを行う必要があるため、コストがかかります。各GET操作の間には遅延があります。
ランダムIOは、シークが頻繁に行われるIOに最適です。
PositionedReadable
APIを使用して読み取られます。read()
呼び出しまたは小さな read(buffer)
呼び出しはほとんどまたはまったく使用しない。目的のfadviseポリシーは、ファイルシステムインスタンスが作成されるときに、構成オプション fs.s3a.experimental.input.fadvise
で設定する必要があります。つまり、ファイルごとの読み取りではなく、ファイルシステムごとにのみ設定できます。
<property> <name>fs.s3a.experimental.input.fadvise</name> <value>random</value> <description> Policy for reading files. Values: 'random', 'sequential' or 'normal' </description> </property>
HDFS-2744、fadviseを許可するようにFSDataInputStreamを拡張する は、入力ストリームにfadviseポリシーを設定するためのパブリックAPIを追加することを提案しています。実装されると、これが入力IOポリシーの構成に使用されるサポートされているメカニズムになります。
normal
(デフォルト)normal
ポリシーは、sequential
モードでファイルの読み取りを開始しますが、呼び出し元がストリーム内で後方にシークすると、シーケンシャルから random
に切り替わります。
このポリシーは、基本的に、ファイルの最後にシークし、インデックスデータを読み込み、次に後方にシークして列を選択的に読み込む列指向ストレージ形式 (例: Apache ORCおよびApache Parquet) の最初の読み取りパターンを認識します。最初のシークはランダムポリシーと比較してコストがかかる場合がありますが、全体的なプロセスは、random
ポリシーでファイルを順次読み取るか、sequential
ポリシーで列指向データを読み取るよりもはるかにコストが低くなります。
Hadoop MapReduce、Apache Hive、Apache Sparkはすべて、HDFSや同様のファイルシステムに作業結果を書き込みます。S3を宛先として使用する場合、rename()
がコピーと削除で模倣されるため、処理が遅くなります。
出力のコミットに時間がかかる場合は、標準のFileOutputCommitter
を使用しているためです。
問題はパフォーマンスにあるように見えるかもしれませんが、それは根本的な問題の兆候です。S3Aが名前変更操作を偽装する方法では、名前変更を出力コミットアルゴリズムで安全に使用することはできません。
修正: 専用のS3Aコミッターのいずれかを使用してください。
単一のユーザーとして、単一のバケットと対話する各S3Aクライアントは、アップロードおよびコピー操作に使用されるスレッドのプールに加えて、オープンなHTTP 1.1接続の専用プールを持っています。デフォルトのプールサイズは、パフォーマンスとメモリ/スレッドの使用量のバランスを取るように意図されています。
プロパティを設定することにより、並列IO(特にアップロード)のためのより大きな(再利用された)HTTP接続とスレッドのプールを持つことができます。
プロパティ | 意味 | デフォルト |
---|---|---|
fs.s3a.threads.max |
AWS転送マネージャーのスレッド | 10 |
fs.s3a.connection.maximum |
HTTP接続の最大数 | 10 |
多くのIOを実行するプロセス(DistCp
、Sparkワーカーなど)には、より大きな値を使用することをお勧めします。
<property> <name>fs.s3a.threads.max</name> <value>20</value> </property> <property> <name>fs.s3a.connection.maximum</name> <value>20</value> </property>
ただし、多くの並列クエリを実行するプロセスは、各クエリが異なるS3バケットのセットで動作している場合、または異なるユーザーの代わりに動作している場合、大量のリソースを消費する可能性があることに注意してください。
fs.s3a.block.size
データをアップロードする場合、fs.s3a.block.size
オプションで設定されたブロックでアップロードされます。デフォルト値は「32M」で32メガバイトです。
より大きな値が使用されると、アップロードが開始される前により多くのデータがバッファリングされます。
<property> <name>fs.s3a.block.size</name> <value>128M</value> </property>
これは、S3にデータをアップロードするために作成されるPUT/POSTリクエストが少なくなり、S3がクライアントをスロットリングする可能性が低くなることを意味します。
大きなファイルをアップロードする場合、ブロックはディスクに保存され、アップロードのためにキューに入れられ、複数のスレッドが異なるブロックを並行してアップロードします。
fs.s3a.fast.upload.buffer
オプションをbytebuffer
に設定するか、オンヒープストレージの場合はarray
に設定することで、ブロックをメモリにバッファリングできます。
メモリにバッファリングすると、メモリ不足になりやすくなります。オプションfs.s3a.fast.upload.active.blocks"
は、S3に書き込む単一の出力ストリームが一度にキューに入れることができるアクティブなブロック数を調整するために存在します。
バッファリングされた各ブロックのサイズはfs.s3a.block.size
の値によって決定されるため、ブロックサイズが大きいほど、メモリ不足になる可能性が高くなります。
DistCPは、特に操作のパラメータとオプションがS3での作業用に調整されていない場合、遅くなる可能性があります。
問題を悪化させるために、DistCPは常に作業対象のバケットに大きな負荷をかけます。これにより、S3はリクエストをスロットリングします。特に、ディレクトリ操作、新しいデータのアップロード、削除操作などをスロットリングします。
-numListstatusThreads <threads>
: デフォルト(1)よりも高い値に設定します。-bandwidth <mb>
: ワーカーごとのアップロード帯域幅を制限するために使用します-m <maps>
: マッパーの数、したがってS3バケットへの負荷を制限します。-m
オプションを使用してマップを追加しても、パフォーマンスが向上する保証はありません。スロットリングの量が増加するだけの場合があります。マップごとの帯域幅が高い、より少ないマップの方が効率的な場合があります。
DistCpの-atomic
オプションは、データをディレクトリにコピーし、コピーが実行される場所に名前を変更します。これはパフォーマンスを低下させます。
-atomic
オプションを使用しないでください。-append
操作はS3でサポートされていません。避けてください。-p
S3にはPOSIXスタイルのアクセス許可モデルがありません。これは失敗します。前述のように、fs.s3a.threads.max
とfs.s3a.connection.maximum
に大きな値を使用します。
バケットがsequential
またはnormal
のfadviseシークポリシーを使用していることを確認してください。つまり、fs.s3a.experimental.input.fadvise
がrandom
に設定されていないことを確認してください。
-numListstatusThreads
をより高い数値に設定して、リストを並行して実行します。fs.s3a.connection.maximum
が使用される値以上であることを確認してください。
-delete
を使用する場合は、fs.trash.interval
を0に設定して、削除されたオブジェクトがごみ箱ディレクトリにコピーされないようにします。
メモリ内にバッファリングするためにfs.s3a.fast.upload.buffer
を切り替えないでください。1つのdistcpマッパーがメモリ不足になると失敗し、ジョブ全体が失敗するリスクがあります。デフォルト値のdisk
を維持する方が安全です。
潜在的に有用なのは、より大きなブロックでアップロードすることです。これはHTTP接続の使用という点でより効率的であり、S3バケット/シャードに対するIOPレートを下げます。
<property> <name>fs.s3a.threads.max</name> <value>20</value> </property> <property> <name>fs.s3a.connection.maximum</name> <value>30</value> <descriptiom> Make greater than both fs.s3a.threads.max and -numListstatusThreads </descriptiom> </property> <property> <name>fs.s3a.experimental.input.fadvise</name> <value>normal</value> </property> <property> <name>fs.s3a.block.size</name> <value>128M</value> </property> <property> <name>fs.s3a.fast.upload.buffer</name> <value>disk</value> </property> <property> <name>fs.trash.interval</name> <value>0</value> </property>
fs -rm
hadoop fs -rm
コマンドは、ファイルを削除するのではなく、.Trash
の下に名前を変更できます。その手順を削除するには、-skipTrash
を使用します。
これはプロパティfs.trash.interval
で設定できます。デフォルトは0ですが、ほとんどのHDFSデプロイメントでは、データ損失のリスクを軽減するためにゼロ以外の値に設定されています。
<property> <name>fs.trash.interval</name> <value>0</value> </property>
Amazon S3は、一連のフロントエンドサーバーを使用して、基になるデータへのアクセスを提供します。使用するフロントエンドサーバーの選択は、負荷分散DNSサービスによって処理されます。S3バケットのIPアドレスが検索されると、クライアントに返すIPアドレスの選択は、フロントエンドサーバーの現在の負荷に基づいて行われます。
時間の経過とともに、フロントエンド全体の負荷が変化するため、「負荷が軽い」と見なされるサーバーは変化します。DNSの値が一定時間キャッシュされると、アプリケーションが過負荷のサーバーと通信してしまう可能性があります。または、障害が発生した場合、存在しなくなったサーバーと通信しようとする可能性があります。
そして、デフォルトでは、アプレット時代の歴史的なセキュリティ上の理由から、JVMのDNS TTLは「無限」です。
AWSとより適切に連携するには、S3を操作するアプリケーションのDNS Time-To-Liveをより低い値に設定します。 AWSドキュメントを参照してください。
この例については、HADOOP-13871で説明されています。
curl
を使用しますcurl -O https://landsat-pds.s3.amazonaws.com/scene_list.gz
nettop
を使用して、プロセスの接続を監視します。特定のS3バケット(またはその内部のシャード)に対して多くのリクエストが行われると、S3は503「スロットリング」応答で応答します。スロットリングは、全体的な負荷が減少すれば回復できます。さらに、オブジェクトストアへの変更が行われる前に送信されるため、本質的にべき等です。このため、クライアントは常にスロットリングされたリクエストを再試行しようとします。
スロットリングされたリクエストを再試行できる回数の制限と、試行間の指数関数的な間隔の増加は、他の再試行制限とは独立して構成できます。
<property> <name>fs.s3a.retry.throttle.limit</name> <value>20</value> <description> Number of times to retry any throttled request. </description> </property> <property> <name>fs.s3a.retry.throttle.interval</name> <value>500ms</value> <description> Interval between retry attempts on throttled requests. </description> </property>
クライアントがAWSServiceThrottledException
エラーで失敗する場合は、間隔と制限を大きくすると、これに対処できる可能性があります。ただし、これは、AWSサービスがクライアントの数とリクエストのレートによって過負荷になっている兆候です。データを異なるバケットに分散するか、よりバランスの取れたディレクトリ構造を使用すると、有益な場合があります。 AWSドキュメントを参照してください。
SSE-KMSで暗号化されたデータの読み取りまたは書き込みは、S3にAWS KMSキー管理サービスの呼び出しを強制します。これには、独自のリクエストレート制限があります。これらは、すべてのアカウント、すべてのキー、およびそれらのすべての用途でデフォルトで1秒あたり1200に設定されています。つまり、S3の場合、SSE-KMSで暗号化されたデータを持つすべてのバケットに適用されます。
distcp
コピーのような大規模な操作で多くのスロットリング応答が見られる場合は、バケットを操作しようとするプロセスの数を減らしてください(distcpの場合:-m
オプションを使用してマッパーの数を減らします)。
ファイルリストを読み書きしている場合は、単純なソートされた順序で処理されないようにリストをランダム化すると、特定のS3データのシャードへの負荷を減らし、それによってスループットを向上させることができます。
S3バケットは、同時に接続しているすべてのクライアントからのリクエストによってスロットリングされます。異なるアプリケーションとジョブは互いに干渉する可能性があります。トラブルシューティングを行う際は、そのことを考慮してください。データを異なるバケットに分割すると、ここで負荷を分離するのに役立つ場合があります。
SSE-KMSで暗号化されたデータを使用している場合は、これも適用されます。これらはS3の数値よりも厳格です。これらの制限に達していると思われる場合は、制限を増やすことができる場合があります。 KMSレート制限ドキュメントを参照してください。
Hadoop APIを介してS3またはその他のオブジェクトストアを操作するアプリケーションを作成する場合の、いくつかのベストプラクティスを次に示します。
listStatus(path)
ではなく、listFiles(path, recursive)
を使用してください。再帰的な listFiles()
呼び出しは、パスの深さに関係なく、1 回の LIST 呼び出しでパスのすべての依存関係を列挙できます。対照的に、クライアントで実装されたディレクトリツリーウォークは、各ディレクトリをスキャンするために複数の HTTP リクエストを発行します。
getFileStats()
の結果をキャッシュし、繰り返し要求しないようにしてください。これには、getFileStatus()
の単なるラッパーである isFile()
、isDirectory()
の使用も含まれます。
操作のソースが見つからない場合は、操作を条件付きで呼び出す前に独自のファイルプローブを実装するのではなく、FileNotFoundException
が発生することに依存してください。
rename()
データを一時ファイルにアップロードし、rename()
を使用して最終パスにコミットするアルゴリズムは避けてください。HDFS では、これは高速なコミット操作を提供します。S3、Wasb、その他のオブジェクトストアでは、書き込みをクローズするまでファイルが表示されないことを知った上で、直接宛先に書き込むことができます。書き込み自体はアトミックです。
rename()
操作は、ソースが見つからない場合、false
を返すことがあります。これは API の弱点です。rename
を呼び出す前にチェックを行い、新しい rename() 呼び出しが公開された場合は、それに切り替えることを検討してください。
delete(path, recursive)
delete(path, recursive)
は、パスが存在しない場合は何も処理しないことに注意してください。そのため、呼び出す前にパスが存在するかどうかをチェックする必要はありません。
delete()
は、クリーンアップ操作としてよく使用されます。オブジェクトストアでは、これは遅く、呼び出し元が即時応答を期待する場合、問題を引き起こす可能性があります。たとえば、スレッドが長時間ブロックされ、他の活性チェックが失敗し始める可能性があります。これらのバックグラウンドクリーンアップ操作を実行するために、executor スレッドを生成することを検討してください。
デフォルトでは、S3A は HTTPS を使用して AWS サービスと通信します。これは、S3 とのすべての通信が SSL を使用して暗号化されることを意味します。この暗号化のオーバーヘッドにより、アプリケーションの速度が大幅に低下する可能性があります。構成オプション fs.s3a.ssl.channel.mode
を使用すると、アプリケーションは特定の SSL 最適化をトリガーできます。
デフォルトでは、fs.s3a.ssl.channel.mode
は default_jsse
に設定されており、SSL の Java Secure Socket Extension 実装を使用します (これは Java を実行する場合のデフォルト実装です)。ただし、1 つ違いがあり、Java 8 で実行する場合、GCM 暗号が有効な暗号スイートのリストから削除されます。GCM 暗号には、Java 8 で実行する場合にパフォーマンス上の問題があることが知られています。詳細については、HADOOP-15669 および HADOOP-16050 を参照してください。GCM 暗号が無効になるのは Java 8 のみであることに注意することが重要です。GCM のパフォーマンスは Java 9 で改善されているため、default_jsse
が指定され、アプリケーションが Java 9 で実行されている場合、通常の JSSE で実行する場合と比較して違いは見られないはずです。
fs.s3a.ssl.channel.mode
は default_jsse_with_gcm
に設定できます。このオプションは、Java 8 の暗号スイートのリストに GCM を含めるため、通常の JSSE で実行する場合と同等です。
実験的な機能
HADOOP-16050 および HADOOP-16346 の時点では、fs.s3a.ssl.channel.mode
を default
または openssl
のいずれかに設定して、HTTPS リクエストのネイティブ OpenSSL アクセラレーションを有効にできます。OpenSSL は、ネイティブコードを使用して SSL および TLS プロトコルを実装します。HTTPS 経由で大量のデータを読み取るユーザーの場合、OpenSSL は JSSE よりも大幅なパフォーマンス上の利点を提供できます。
S3A は、WildFly OpenSSL ライブラリを使用して、OpenSSL を Java JSSE API にバインドします。このライブラリを使用すると、S3A は OpenSSL を使用して透過的にデータを読み取ることができます。wildfly-openssl
ライブラリは S3A のオプションのランタイム依存関係であり、Java JSSE を OpenSSL にバインドするためのネイティブライブラリが含まれています。
WildFly OpenSSL は OpenSSL 自体をロードする必要があります。これは、システムプロパティ org.wildfly.openssl.path
を使用して実行できます。たとえば、HADOOP_OPTS="-Dorg.wildfly.openssl.path=<OpenSSL ライブラリへのパス> ${HADOOP_OPTS}"
のようにします。詳細については、WildFly OpenSSL のドキュメントを参照してください。
fs.s3a.ssl.channel.mode
が default
に設定されている場合、S3A は WildFly ライブラリを使用して OpenSSL ライブラリのロードを試みます。失敗した場合、default_jsse
の動作にフォールバックします。
fs.s3a.ssl.channel.mode
が openssl
に設定されている場合、S3A は WildFly を使用して OpenSSL ライブラリのロードを試みます。失敗した場合、例外がスローされ、S3A の初期化は失敗します。
fs.s3a.ssl.channel.mode
の構成fs.s3a.ssl.channel.mode
は次のように構成できます。
<property> <name>fs.s3a.ssl.channel.mode</name> <value>default_jsse</value> <description> If secure connections to S3 are enabled, configures the SSL implementation used to encrypt connections to S3. Supported values are: "default_jsse", "default_jsse_with_gcm", "default", and "openssl". "default_jsse" uses the Java Secure Socket Extension package (JSSE). However, when running on Java 8, the GCM cipher is removed from the list of enabled ciphers. This is due to performance issues with GCM in Java 8. "default_jsse_with_gcm" uses the JSSE with the default list of cipher suites. "default_jsse_with_gcm" is equivalent to the behavior prior to this feature being introduced. "default" attempts to use OpenSSL rather than the JSSE for SSL encryption, if OpenSSL libraries cannot be loaded, it falls back to the "default_jsse" behavior. "openssl" attempts to use OpenSSL as well, but fails if OpenSSL libraries cannot be loaded. </description> </property>
fs.s3a.ssl.channel.mode
でサポートされている値
fs.s3a.ssl.channel.mode の値 |
説明 |
---|---|
default_jsse |
Java 8 で GCM を使用せずに Java JSSE を使用します |
default_jsse_with_gcm |
Java JSSE を使用します |
デフォルト |
OpenSSL を使用し、OpenSSL をロードできない場合は default_jsse にフォールバックします |
openssl |
OpenSSL を使用し、OpenSSL をロードできない場合は失敗します |
命名規則は、HADOOP-15669 の ABFS サポートとの下位互換性を維持するために設定されています。
SSL の最適化が進むにつれて、fs.s3a.ssl.channel.mode
に他のオプションが将来追加される可能性があります。
OpenSSL アクセラレーションを機能させるには、互換性のあるバージョンの wildfly JAR がクラスパス上にある必要があります。これは、オプションであるため、公開された hadoop-aws
モジュールの依存関係で明示的に宣言されていません。
wildfly JAR が見つからない場合、ネットワークアクセラレーションは常に JVM にフォールバックします。
注意: 過去に wildfly JAR と openSSL リリースの間に互換性の問題が発生しています。バージョン 1.0.4.Final は openssl 1.1.1 と互換性がありませんでした。さらに複雑なのは、hadoop-azure-datalake
で使用されている古いバージョンの azure-data-lake-store-sdk
JAR には、1.0.4.Final クラスのシェーディングされていないコピーが含まれており、より新しいバージョンが明示的にクラスパスに配置されている場合でもバインディングの問題が発生していました。
S3A Filesystem インスタンスが作成および初期化されると、クライアントは指定されたバケットが有効かどうかをチェックします。これは時間がかかる場合があります。fs.s3a.bucket.probe
を次のように構成することで、バケット検証を無視できます。
<property> <name>fs.s3a.bucket.probe</name> <value>0</value> </property>
注意: バケットが存在しない場合、この問題はファイルシステムで操作が実行されたときに表面化します。UnknownStoreException
スタックトレースが表示されます。
アプリケーションは通常、FileSystem.get()
または Path.getFileSystem()
を介して、共有キャッシュからファイルシステムを要求します。キャッシュ FileSystem.CACHE
は、ユーザーごとに、指定された URI のファイルシステムのインスタンスを 1 つキャッシュします。s3a://landsat-pds/
などの URI のキャッシュされた FS に対する FileSystem.get
のすべての呼び出しは、その 1 つのインスタンスを返します。
FileSystem インスタンスは、キャッシュに対してオンデマンドで作成され、インスタンスを要求する各スレッドで実行されます。これは、同期ブロックの外で行われます。タスクが初期化された FileSystem インスタンスを持っていると、同期ブロックでそれをキャッシュに追加します。キャッシュがその URI のインスタンスをすでに持っていることが判明した場合、キャッシュされたコピーを元に戻し、作成したばかりの FS インスタンスを閉じます。
FileSystem の初期化に時間がかかり、多くのスレッドが同じ S3 バケットの FileSystem インスタンスを並行して取得しようとしている場合、スレッドの 1 つを除くすべてが無駄な作業を行い、共有オブジェクトで意図せずにロックの競合を引き起こす可能性があります。
並行して作成できる FS インスタンスの数を制限するためにセマフォを使用するオプション fs.creation.parallel.count
があります。
これを低い数値に設定すると、異なるオブジェクトストア/分散ファイルシステムに対して同時に作成できる FileSystem クライアントの数が制限される代わりに、無駄な作業の量が減ります。
たとえば、値が 4 の場合、s3a://landsat-pds/
バケットのコネクタの無駄なインスタンス化の数に上限が設定されます。
<property> <name>fs.creation.parallel.count</name> <value>4</value> </property>
また、4 つのスレッドがこのようなコネクタを作成している場合、他のバケットのコネクタを作成しようとするすべてのスレッドもブロックされることになります。
多くのスレッドが同じ初期化に時間がかかるオブジェクトストアと同時に対話しようとする可能性のあるアプリケーションを実行する場合は、これを試してみることを検討してください。