升级EMR 7.0.0(Spark3.5.0)后写入S3遇400 Bad Request错误
问题分析与解决方案
核心问题排查与修复
1. 移除AWS SDK v1依赖,避免版本冲突
EMR 7.0.0 及 Hadoop 3.3.6 默认使用 AWS SDK v2,而你的依赖中同时引入了 AWS SDK v1(com.amazonaws:aws-java-sdk),这会导致类加载冲突,引发S3请求的400错误。
修改你的依赖列表,移除aws-java-sdk:
libraryDependencies ++= Seq( "org.apache.kafka" %% "kafka" % "3.4.1", "org.apache.spark" %% "spark-sql-kafka-0-10" % "3.5.0", "org.apache.spark" %% "spark-core" % "3.5.0", "org.apache.spark" %% "spark-sql" % "3.5.0", "org.apache.spark" %% "spark-streaming" % "3.5.0", "org.apache.hadoop" % "hadoop-aws" % "3.3.6" )
2. 验证S3路径与区域配置
- 确认S3桶所在区域为
eu-west-1,与EMR集群区域一致;若桶在其他区域,需显式配置S3端点:
在Spark启动参数中添加:--conf fs.s3a.endpoint=s3.eu-west-1.amazonaws.com - 若桶名包含特殊字符(如
.),需启用路径样式访问:--conf fs.s3a.path.style.access=true
3. 检查EMR角色的权限边界与信任关系
- 确认
EMR_DefaultRole_v2的信任策略允许elasticmapreduce.amazonaws.com扮演该角色:
信任策略示例:{ "Version": "2008-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "elasticmapreduce.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } - 检查角色是否存在权限边界限制,若有需确保边界允许S3全访问操作。
4. 优化Spark分区写入逻辑(可选)
Spark 3.x 对分区写入逻辑有优化,可移除repartition与partitionBy的重复分区键,避免不必要的数据 shuffle:
df .write .partitionBy("year", "month", "day") .mode(saveMode) .parquet(path)
使用Request ID调试S3请求日志
1. 通过AWS CloudTrail查询详细请求
- 登录AWS控制台,进入CloudTrail服务;
- 在“事件历史”中筛选:
- 事件源:
s3.amazonaws.com - 请求ID:填入你获取的
JB2KN3QAMSCD504T等ID;
- 事件源:
- 找到对应事件后,查看“请求参数”和“错误代码”字段,获取具体错误原因(如签名错误、路径非法等)。
2. 查看S3服务器访问日志
若你的S3桶已开启服务器访问日志:
- 找到日志存储的目标桶;
- 根据请求发生时间,查找对应的日志文件;
- 在日志中搜索目标Request ID,可看到完整的请求头、响应状态及错误详情。
3. 检查EMR集群日志
EMR会将集群日志上传到S3的默认路径(通常为s3://aws-logs-<账号ID>-<区域>/elasticmapreduce/<集群ID>/):
- 进入对应集群的日志路径,查找
hadoop-yarn或spark目录下的日志文件; - 搜索S3请求的错误栈,获取更详细的客户端侧请求信息。
内容的提问来源于stack exchange,提问作者beikern
相关产品推荐
相关产品推荐

