Apache Spark s3a 提交者 - 线程堆栈 - 内存不足问题

Posted

技术标签:

【中文标题】Apache Spark s3a 提交者 - 线程堆栈 - 内存不足问题【英文标题】:Apache Spark s3a committer - thread stack - out of memory issues 【发布时间】:2022-01-02 04:06:33 【问题描述】:

我真的需要一些帮助:

我们正在使用 Spark3.1.2 和独立集群。 自从我们开始使用 s3a 目录提交器后,我们的 Spark 作业稳定性和性能显着提高!

然而,最近几天我们对解决这个 s3a 目录提交程序问题感到完全困惑,想知道您是否知道发生了什么?

我们的 spark 作业因 Java OOM(或者更确切地说是进程限制)错误而失败:

 An error occurred while calling None.org.apache.spark.api.java.JavaSparkContext.

: java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached
    at java.base/java.lang.Thread.start0(Native Method)
    at java.base/java.lang.Thread.start(Thread.java:803)
    at java.base/java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:937)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1343)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
    at java.base/java.util.concurrent.Executors$DelegatedExecutorService.submit(Executors.java:714)
    at org.apache.spark.rpc.netty.DedicatedMessageLoop.$anonfun$new$1(MessageLoop.scala:174)
    at org.apache.spark.rpc.netty.DedicatedMessageLoop.$anonfun$new$1$adapted(MessageLoop.scala:173)
    at scala.collection.immutable.Range.foreach(Range.scala:158)
    at org.apache.spark.rpc.netty.DedicatedMessageLoop.<init>(MessageLoop.scala:173)
    at org.apache.spark.rpc.netty.Dispatcher.liftedTree1$1(Dispatcher.scala:75)
    at org.apache.spark.rpc.netty.Dispatcher.registerRpcEndpoint(Dispatcher.scala:72)
    at org.apache.spark.rpc.netty.NettyRpcEnv.setupEndpoint(NettyRpcEnv.scala:136)
    at org.apache.spark.storage.BlockManager.<init>(BlockManager.scala:231)
    at org.apache.spark.SparkEnv$.create(SparkEnv.scala:394)
    at org.apache.spark.SparkEnv$.createDriverEnv(SparkEnv.scala:189)
    at org.apache.spark.SparkContext.createSparkEnv(SparkContext.scala:277)
    at org.apache.spark.SparkContext.<init>(SparkContext.scala:458)
    at org.apache.spark.api.java.JavaSparkContext.<init>(JavaSparkContext.scala:58)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:247)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:238)
    at py4j.commands.ConstructorCommand.invokeConstructor(ConstructorCommand.java:80)
    at py4j.commands.ConstructorCommand.execute(ConstructorCommand.java:69)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.base/java.lang.Thread.run(Thread.java:834)

Spark Thread Dump 在 spark 驱动程序上显示超过 5000 个提交者线程! 这是一个例子:

Thread ID   Thread Name Thread State    Thread Locks
1047    s3-committer-pool-0 WAITING 
1449    s3-committer-pool-0 WAITING 
1468    s3-committer-pool-0 WAITING 
1485    s3-committer-pool-0 WAITING 
1505    s3-committer-pool-0 WAITING 
1524    s3-committer-pool-0 WAITING 
1529    s3-committer-pool-0 WAITING 
1544    s3-committer-pool-0 WAITING 
1549    s3-committer-pool-0 WAITING 
1809    s3-committer-pool-0 WAITING 
1972    s3-committer-pool-0 WAITING 
1998    s3-committer-pool-0 WAITING 
2022    s3-committer-pool-0 WAITING 
2043    s3-committer-pool-0 WAITING 
2416    s3-committer-pool-0 WAITING 
2453    s3-committer-pool-0 WAITING 
2470    s3-committer-pool-0 WAITING 
2517    s3-committer-pool-0 WAITING 
2534    s3-committer-pool-0 WAITING 
2551    s3-committer-pool-0 WAITING 
2580    s3-committer-pool-0 WAITING 
2597    s3-committer-pool-0 WAITING 
2614    s3-committer-pool-0 WAITING 
2631    s3-committer-pool-0 WAITING 
2726    s3-committer-pool-0 WAITING 
2743    s3-committer-pool-0 WAITING 
2763    s3-committer-pool-0 WAITING 
2780    s3-committer-pool-0 WAITING 
2819    s3-committer-pool-0 WAITING 
2841    s3-committer-pool-0 WAITING 
2858    s3-committer-pool-0 WAITING 
2875    s3-committer-pool-0 WAITING 
2925    s3-committer-pool-0 WAITING 
2942    s3-committer-pool-0 WAITING 
2963    s3-committer-pool-0 WAITING 
2980    s3-committer-pool-0 WAITING 
3020    s3-committer-pool-0 WAITING 
3037    s3-committer-pool-0 WAITING 
3055    s3-committer-pool-0 WAITING 
3072    s3-committer-pool-0 WAITING 
3127    s3-committer-pool-0 WAITING 
3144    s3-committer-pool-0 WAITING 
3163    s3-committer-pool-0 WAITING 
3180    s3-committer-pool-0 WAITING 
3222    s3-committer-pool-0 WAITING 
3242    s3-committer-pool-0 WAITING 
3259    s3-committer-pool-0 WAITING 
3278    s3-committer-pool-0 WAITING 
3418    s3-committer-pool-0 WAITING 
3435    s3-committer-pool-0 WAITING 
3452    s3-committer-pool-0 WAITING 
3469    s3-committer-pool-0 WAITING 
3486    s3-committer-pool-0 WAITING 
3491    s3-committer-pool-0 WAITING 
3501    s3-committer-pool-0 WAITING 
3508    s3-committer-pool-0 WAITING 
4029    s3-committer-pool-0 WAITING 
4093    s3-committer-pool-0 WAITING 
4658    s3-committer-pool-0 WAITING 
4666    s3-committer-pool-0 WAITING 
4907    s3-committer-pool-0 WAITING 
5102    s3-committer-pool-0 WAITING 
5119    s3-committer-pool-0 WAITING 
5158    s3-committer-pool-0 WAITING 
5175    s3-committer-pool-0 WAITING 
5192    s3-committer-pool-0 WAITING 
5209    s3-committer-pool-0 WAITING 
5226    s3-committer-pool-0 WAITING 
5395    s3-committer-pool-0 WAITING 
5634    s3-committer-pool-0 WAITING 
5651    s3-committer-pool-0 WAITING 
5668    s3-committer-pool-0 WAITING 
5685    s3-committer-pool-0 WAITING 
5702    s3-committer-pool-0 WAITING 
5722    s3-committer-pool-0 WAITING 
5739    s3-committer-pool-0 WAITING 
6144    s3-committer-pool-0 WAITING 
6167    s3-committer-pool-0 WAITING 
6289    s3-committer-pool-0 WAITING 
6588    s3-committer-pool-0 WAITING 
6628    s3-committer-pool-0 WAITING 
6645    s3-committer-pool-0 WAITING 
6662    s3-committer-pool-0 WAITING 
6675    s3-committer-pool-0 WAITING 
6692    s3-committer-pool-0 WAITING 
6709    s3-committer-pool-0 WAITING 
7049    s3-committer-pool-0 WAITING 

这是考虑到我们的设置不允许超过 100 个线程... 或者我们有什么不明白的……

这是我们的配置和设置:

fs.s3a.threads.max  100 
fs.s3a.connection.maximum  1000 
fs.s3a.committer.threads 16   
fs.s3a.max.total.tasks  5
fs.s3a.committer.name   directory
fs.s3a.fast.upload.buffer                 disk
io.file.buffer.size                                1048576
mapreduce.outputcommitter.factory.scheme.s3a    - org.apache.hadoop.fs.s3a.commit.S3ACommitterFactory

我们尝试了不同版本的 spark Hadoop 云库,但问题始终相同。

https://repository.cloudera.com/content/repositories/releases/org/apache/spark/spark-hadoop-cloud_2.11/2.4.0-cdh6.3.2/spark-hadoop-cloud_2.11-2.4.0-cdh6.3.2.jar

https://repository.cloudera.com/artifactory/libs-release-local/org/apache/spark/spark-hadoop-cloud_2.11/2.4.0.7.0.3.0-79/spark-hadoop-cloud_2.11-2.4.0.7.0.3.0-79.jar

https://repo1.maven.org/maven2/org/apache/spark/spark-hadoop-cloud_2.12/3.2.0/spark-hadoop-cloud_2.12-3.2.0.jar

https://repository.cloudera.com/artifactory/libs-release-local/org/apache/spark/spark-hadoop-cloud_2.12/3.1.2.7.2.12.0-291/spark-hadoop-cloud_2.12-3.1.2.7.2.12.0-291.jar

如果您能指出我们正确的方向,我们将不胜感激????

感谢您的宝贵时间!

【问题讨论】:

你有多少空间:$fs.s3a.committer.staging.tmp.path/$user? 您能否在集群中使用的所有机器上添加:“ulimit -Hn”的输出。 docs.cloudera.com/HDPDocuments/HDP2/HDP-2.6.1/bk_security/… ulimit -Hn 1048576 $fs.s3a.committer.staging.tmp.path 是 3TB 的 HDFS 文件系统 - 为空。 你能添加你的配置吗:fs.s3a.buffer.dir 是否和 fs.s3a.committer.staging.tmp.path 一样? 尝试减少:线程数 fs.s3a.threads.max 20 问题有变化吗? 【参考方案1】:

将是HADOOP-16570 S3A 提交者在大规模提交作业/任务时泄漏线程/引发 OOM

升级到 hadoop-3.3.0 二进制文件以进行修复。理想情况下到 3.3.1 修复一些其他问题,尤其是来自 spark 的重复 jobID。不确定该修复程序可以追溯到 CDH 版本多远;如果你现在真的需要,我可以解决。当然不是 CDH6.x

【讨论】:

非常感谢!事实上,我们所做的一切都无济于事。 我们现在的问题是寻找正确的驱动程序 - 我们在哪里可以获取相关版本的 spark-cloud jar?此驱动程序是否适用于 Spark 3.1.2:mvnrepository.com/artifact/org.apache.spark/… ?? spark cloud jar 必须是您的 spark 发行版的那个;它只是一个瘦绑定类 嗨,我们正在尝试在与 Hadoop 3.2 捆绑在一起的 Spark 3.1.2 上启用此功能。为 3.3.1 和 Hadoop 3.2 库一起提供 spark-hadoop-cloud 是否安全? (我们正在尝试使用未捆绑的版本,并且遇到了 Zookeeper 馆长库与 Guava 不匹配的问题。更快的方法是使用捆绑的版本,只需添加 3.3.1 的提交者。它会工作吗?)。谢谢! 线程泄漏在hadoop-aws;它应该只是需要更新的 hadoop-*。【参考方案2】:

查看 this article 以了解 S3A 的调整。

具体来说,即使它归类为数组,我也会看一下:

您可能需要仔细调整以降低内存不足的风险,尤其是当数据缓冲在内存中时。有一个 可以调整的参数个数:

文件系统中可用于数据的线程总数 上传或任何其他排队的文件系统操作。这是设置在 fs.s3a.threads.max.

可以排队等待执行的操作数,等待一个 线。这是在 fs.s3a.max.total.tasks 中设置的。

单个输出流可以激活的块数 (即被线程上传或在文件系统中排队 线程队列)。这是在 fs.s3a.fast.upload.active.blocks 中设置的。

空闲线程可以在线程池中停留的时间长度 在它退役之前。这是在 fs.s3a.threads.keepalivetime 中设置的。

我认为您可能会发现减少线程数会消除内存压力。

我还建议你调整fs.s3a.fast.upload.active.blocks 它也可以减轻内存压力。我认为减少线程数应该是您的第一步,因为 100 有点激进。您可能会受到带宽的限制,而额外的线程可能除了消耗内存之外什么都不做。

【讨论】:

你知道驱动线程是干什么用的吗?如果我理解正确,配置线程应该是为工人准备的。驱动线程有什么用? 查看 s3 committer 文档。(不是 100% 相同,但学习 s3 和 spark 的好地方)链接如下。它提出了文件与驱动程序通信并提交的想法。我们不知道这个文件写入是否相同,但它似乎合乎逻辑,因为驱动程序是唯一知道作业成功/失败的驱动程序。我没有发现确凿的证据声称这是真的,但这似乎是合理的/似是而非的。 github.com/apache/hadoop/blob/trunk/hadoop-tools/hadoop-aws/src/… 这也是有道理的,为什么每个工作人员使用 100 个线程可能最终导致驱动程序中有 5000 个线程,以及为什么再次考虑使用不会给驱动程序增加太多压力的数字。 (减少你的线程数) 查看@Stevel 的答案 - 这是提交者早期版本的已知 hadoop 错误! 非常感谢您 ping 我。

以上是关于Apache Spark s3a 提交者 - 线程堆栈 - 内存不足问题的主要内容,如果未能解决你的问题,请参考以下文章

Apache Spark Hadoop S3A SignatureDoesNotMatch

如何从 Apache Spark 访问 s3a:// 文件?

如何在 Spark Submit 中将 s3a 与 Apache spark 2.2(hadoop 2.8) 一起使用?

Spark + s3 - 错误 - java.lang.ClassNotFoundException:找不到类 org.apache.hadoop.fs.s3a.S3AFileSystem

使用 Spark 访问 s3a 时出现 403 错误

您可以在 Spark/Hadoop 中将 s3:// 翻译(或别名)为 s3a:// 吗?