Amazon EMR で Spark または Hive ジョブが HTTP 503「Slow Down」AmazonS3Exception で失敗するのはなぜですか?

最終更新日: 2022 年 5 月 17 日

Amazon EMR で Apache Spark または Apache Hive ジョブが、次のように HTTP 503「Slow Down」AmazonS3Exception で失敗します。

java.io.IOException: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: Slow Down (Service: Amazon S3; Status Code: 503; Error Code: 503 Slow Down; Request ID: 2E8B8866BFF00645; S3 Extended Request ID: oGSeRdT4xSKtyZAcUe53LgUf1+I18dNXpL2+qZhFWhuciNOYpxX81bpFiTw2gum43GcOHR+UlJE=), S3 Extended Request ID: oGSeRdT4xSKtyZAcUe53LgUf1+I18dNXpL2+qZhFWhuciNOYpxX81bpFiTw2gum43GcOHR+UlJE=

簡単な説明

このエラーは、アプリケーションの Amazon Simple Storage Service (Amazon S3) リクエスト頻度が、一般的な持続レート (1 秒あたり 5,000 リクエスト) を超え、Amazon S3 の内部でパフォーマンスの最適化が行われている場合に発生します。

Amazon EMR を使用して S3 データにアクセスする際のリクエストの成功率を向上させるには、次のアプローチを試してみてください。

  • S3 リクエストの再試行戦略を変更する。
  • 同時 S3 リクエストの数を調整する。

解決方法

リクエストの数が多すぎる問題を特定するには、S3 バケットの Amazon CloudWatch リクエストメトリクスを設定するのがベストプラクティスです。これらの CloudWatch メトリクスに基づいて、ユースケースに最適なソリューションを決定できます。

CloudWatch リクエストメトリクスを設定する

Amazon S3 リクエストをモニタリングするには、バケットの CloudWatch リクエストメトリクスを有効にします。次に、プレフィックスの フィルターを定義します。モニタリングに役立つメトリクスのリストについては、「Amazon CloudWatch によるメトリクスのモニタリング」を参照してください。

S3 リクエストの再試行戦略を変更する

デフォルトでは、EMRFS はエクスポネンシャルバックオフ戦略を使用して Amazon S3 へのリクエストを再試行します。デフォルトの EMRFS 再試行制限は 15 です。しかし、新しいクラスターや実行中のクラスターの再試行制限、またはアプリケーションランタイムの再試行制限を引き上げることができます。

再試行制限を増やすには、fs.s3.maxRetries パラメータの値を変更します。このパラメータに非常に高い値を設定すると、ジョブの実行時間が長くなることがあります。このパラメータを高い値 (20 など) に設定し、ジョブの継続時間のオーバーヘッドを監視し、ユースケースに基づいてこのパラメーターを調整してみてください。

新しいクラスターの場合、クラスターの起動時に次のような設定オブジェクトを追加できます。

[
  {
    "Classification": "emrfs-site",
    "Properties": {
      "fs.s3.maxRetries": "20"
    }
  }
]

クラスターが起動した後、Amazon EMR 上で実行する Spark および Hive アプリケーションは、この新しい制限を使用します。

実行中のクラスターの再試行制限を引き上げるには、次の手順を実行します。

1.    Amazon EMR コンソールを開きます。

2.    クラスターのリストで、[名前] で再設定するアクティブなクラスターを選択します。

3.    クラスターの詳細ページを開いて [設定] タブを選択します。

4.    [フィルター] ドロップダウンリストで、再設定するインスタンスグループを選択します。

5.    [再設定] ドロップダウンリストで、[テーブルで編集] を選択します。

6.    設定分類のテーブルで、[設定を追加] を選択し、次のように入力します。

[分類] : emrfs-site

[プロパティ] : fs.s3.maxRetries

[] : 再試行制限の新しい値 (例: 20)

7.    [この設定をすべてのアクティブなインスタンスグループに適用] を選択します。

8.    [変更の保存] をクリックします。

設定がデプロイされると、Spark および Hive アプリケーションでは新しい制限が使用されます。

ランタイムの再試行制限を増やすには、次のような Spark シェルセッションを使用します。

spark> sc.hadoopConfiguration.set("fs.s3.maxRetries", "20")
spark> val source_df = spark.read.csv("s3://awsexamplebucket/data/")
spark> source_df.write.save("s3://awsexamplebucket2/output/")

Hive アプリケーションの実行時の再試行制限を引き上げる方法の例を次に示します。

hive> set fs.s3.maxRetries=20;
hive> select ....

同時の S3 リクエストの数を調整する

  • 同じS3プレフィックスに対する読み取りと書き込みを行う複数のジョブ (Spark、Apache Hive、または s-dist-cp) がある場合、同時実行数を調整できます。読み取り/書き込みが最も多いジョブから始めて、過度の並列処理を避けるために同時実行数を下げます。Amazon S3 のクロスアカウントアクセスが設定されている場合、他のアカウントも同じプレフィックスにジョブを送信している可能性があることに注意してください。
  • ジョブが宛先バケットに書き込もうとしたときにエラーが表示される場合は、過剰な書き込み並列処理を減らします。例えば、Spark の .coalesce() または .repartition() 演算を使用して、Amazon S3 に書き込む前に Spark 出力パーティションの数を減らします。エグゼキュターあたりのコア数を減らしたり、エグゼキュターの数を減らしたりすることもできます。
  • ジョブがソースバケットから読み取ろうとしたときにエラーが表示される場合は、オブジェクトのサイズを調整します。複数の小さいオブジェクトをいくつかの大きいオブジェクトに集約して、ジョブが読み取るオブジェクトの数を減らすことができます。これを行うと、ジョブはより少ない読み取り要求でデータセットを読み取ることができます。例えば、s3-dist-cp を使用して、多数の小さいファイルを大きなファイルにマージしてファイル数を少なくします。