java - 为什么 Docker 容器中的 Spark 应用程序会失败并出现 OutOfMemoryError : Java heap space?

标签 java amazon-web-services apache-spark docker

我在 AWS Batch Service 上使用 r4.8xlarge 来运行 Spark。这已经是一台大机器了,32 个 vCPU,244 GB。在 AWS Batch Service 上,该进程在 Docker 容器内运行。从多个来源中,我发现我们应该使用带有参数的 java:

-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1

即使使用此参数,进程也不会超过 31GB 常驻内存和 45GB 虚拟内存。

根据我所做的分析:

java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 26.67G
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-1~deb9u1-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)

第二次测试

docker run -it --rm 650967531325.dkr.ecr.eu-west-1.amazonaws.com/java8_aws java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2 -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 26.67G
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-1~deb9u1-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)

第三次测试

java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=10 -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 11.38G
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-1~deb9u1-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)

该系统是使用 Native Packager 作为独立应用程序构建的。 SparkSession 的构建方式如下,Cores 等于 31 (32-1):

SparkSession
  .builder()
  .appName(applicationName)
  .master(s"local[$Cores]")
  .config("spark.executor.memory", "3g")

对egorlitvinenko的回答:

$ docker stats
CONTAINER ID        NAME                                                                    CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
0c971993f830        ecs-marcos-BatchIntegration-DedupOrder-3-default-aab7fa93f0a6f1c86800   1946.34%            27.72GiB / 234.4GiB   11.83%              0B / 0B             72.9MB / 160kB      0
a5d6bf5522f6        ecs-agent                                                               0.19%               19.56MiB / 240.1GiB   0.01%               0B / 0B             25.7MB / 930kB      0

更多测试,现在使用Oracle JDK,内存从未超过4G:

$ 'spark-submit' '--class' 'integration.deduplication.DeduplicationApp' '--master' 'local[31]' '--executor-memory' '3G' '--driver-memory' '3G' '--conf' '-Xmx=150g' '/localName.jar' '--inPath' 's3a://dp-import-marcos-refined/platform-services/order/merged/*/*/*/*' '--outPath' 's3a://dp-import-marcos-refined/platform-services/order/deduplicated' '--jobName' 'DedupOrder' '--skuMappingPath' 's3a://dp-marcos-dwh/redshift/item_code_mapping'

我在 Spark 上使用了参数 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2,显然没有使用所有内存。我该如何解决这个问题?

最佳答案

tl;drspark-submit 时使用 --driver-memory--executor-memory您的 Spark 应用程序或为托管 Spark 应用程序的 JVM 设置正确的内存设置。

<小时/>

驱动程序的内存默认为1024M,您可以使用spark-submit查看:

--driver-memory MEM Memory for driver (e.g. 1000M, 2G) (Default: 1024M).

执行器的内存默认为1G,您可以使用spark-submit再次检查:

--executor-memory MEM Memory per executor (e.g. 1000M, 2G) (Default: 1G).

话虽如此,执行环境总共有多少内存并不重要,因为 Spark 应用程序不会为驱动程序和执行程序使用超过默认 1G 的内存。

由于您使用本地主URL,因此当您执行Spark应用程序时,驱动程序JVM的内存设置已经设置。在创建 SparkSession 时设置内存设置简直太晚了。 Spark 应用程序的单个 JVM(驱动程序和单个执行器都在同一个 JVM 上运行)已经启动,因此任何 config 都无法更改它。

换句话来说,Docker 容器有多少内存对 Spark 应用程序使用多少内存没有影响。它们是独立配置的环境。当然,Docker 容器拥有的内存越多,内部的进程就越多(因此它们确实是互连的)。

spark-submit Spark 应用程序时使用 --driver-memory--executor-memory 或设置正确的内存设置托管 Spark 应用程序的 JVM。

关于java - 为什么 Docker 容器中的 Spark 应用程序会失败并出现 OutOfMemoryError : Java heap space?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49536404/

相关文章:

java - MySQLIntegrityConstraintViolationException 未在异常消息中显示列名

java - LDAP 查询未从 Active Directory 返回正确的数据

scala - 指定值元素上的ReduceByKey

java - 分解JavaPairRDD对象

java - 滑动抽屉未关闭

java - 在jsp中转义<%%>

ios - Swift 4 - 尝试在 AVPlayerViewController 中从后端显示 AWS 视频 url 不起作用,出现奇怪的错误

swift - 如何在 Xcode 的 iOS 项目中设置 AWS 移动 SDK

amazon-web-services - 如何通过 AWS CLI 对一组文件使用通配符 `cp`?

apache-spark - pyspark.sql.DataFrameWriter.saveAsTable() 的格式