问题现象
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) 请求速率(在存储桶中每个前缀在每秒处理 3500 个 PUT/COPY/POST/DELETE 和 5500 个 GET/HEAD 请求)时发生。
解决此问题的方式有两种:
- 减少 Amazon S3 请求的数量。
- 添加更多前缀到 S3 存储桶。
- 提高 EMR 文件系统 (EMRFS) 重试限制。
解决方案
在您可以确定请求过多问题前,首先配置 Amazon CloudWatch 的请求指标
配置 CloudWatch 请求指标
要监控 Amazon S3 请求,为存储桶启用 CloudWatch 请求指标。然后,为前缀定义筛选条件。如需要监控的有用指标列表,见 Amazon S3 CloudWatch 请求指标。
在启用指标后,使用指标中的数据确定以下哪个解决办法最适用于您的用例。
减少 Amazon S3 请求的数量
- 如果多个并发作业(Spark、Apache Hive 或 s3-dist-cp)正在读取或写入相同的 Amazon S3 前缀:减少并发作业的数量。如果为 Amazon S3 配置跨账户访问,记住其他账户也有可能会提交作业到前缀。
- 如果作业尝试写入目标存储桶时发生错误:降低作业的并行性。例如,在写入 Amazon S3 前使用 Spark .coalesce() 或 .repartition() 操作减少 Spark 输出分区的数量。您还可以减少每个执行程序的内核数量,或减少执行程序的数量。
- 如果作业尝试从源存储桶读取时发生错误:减少文件数量,从而减少 Amazon S3 请求的数量。例如,使用 s3-dist-cp 将大量小文件合并成少量大文件。
添加更多前缀到 S3 存储桶
解决 "Slow Down" 错误的另一种方法是,添加更多前缀到 S3 存储桶。存储桶中的前缀数量没有限制。请求速率针对每个前缀,而不是存储桶。
例如,如果您在一个存储桶中创建三个前缀,如下:
- s3://awsexamplebucket/images
- s3://awsexamplebucket/videos
- s3://awsexamplebucket/documents
那么,您可以每秒对该存储桶发出 10500 个写入请求或 16500 个读取请求。
提高 EMRFS 重试限制
默认情况下,EMRFS 重试限制设置为 4。运行以下命令,以确认集群的重试限制:
$ hdfs getconf -confKey fs.s3.maxRetries
- 要提高新集群的重试限制:请在启动集群时添加以下类似的配置对象。
- 要在运行的集群上提高重试限制:请使用以下配置对象覆盖实例组的集群配置(Amazon EMR 版本 5.21.0 及更高版本)。
[
{
"Classification": "emrfs-site",
"Properties": {
"fs.s3.maxRetries": "20"
}
}
]
提高集群的重试限制时,Spark 和 Hive 应用程序页可以使用新限制。以下是使用更高重试限制的 Spark shell 会话的示例:
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/")