Spark本地单元测试抛出内存溢出异常,寻求排查方案
解决Spark+HBase本地单元测试内存溢出问题
兄弟,我之前在做Spark+HBase本地单元测试的时候也踩过这个内存溢出的坑,结合你的场景(Spark2.1.0,先启动HBase MiniCluster再初始化Spark Session),给你几个亲测有效的解决办法:
1. 给测试进程分配足够的JVM堆内存
本地测试同时跑HBase MiniCluster和Spark两个重量级组件,默认的JVM内存肯定不够用,得手动调大:
- 如果是IDE里运行测试,直接在测试的VM参数里添加:
-Xmx4G -Xms2G -XX:MaxPermSize=512M(根据你机器的内存配置调整,比如8G内存可以给到-Xmx6G) - 如果用sbt执行测试,在
build.sbt里配置:javaOptions in Test ++= Seq("-Xmx4G", "-Xms2G", "-XX:MaxPermSize=512M") - 同时别忘了调整Spark自身的内存参数,初始化Spark Session时加上:
val spark = SparkSession.builder() .master("local[*]") .config("spark.driver.memory", "2G") .config("spark.executor.memory", "2G") // 本地模式下executor和driver共用一个进程,这个配置也会生效 .getOrCreate()
2. 优化HBase MiniCluster的内存配置并及时释放资源
HBase MiniCluster默认的内存配置比较高,你可以在启动前调低它的资源占用:
val conf = HBaseConfiguration.create() // 给RegionServer分配1G堆内存,Master分配512M,根据情况调整 conf.setInt("hbase.regionserver.heapsize", 1024) conf.setInt("hbase.master.heapsize", 512) val miniCluster = MiniHBaseCluster.createCluster(conf, 1)
特别重要:测试结束后一定要显式关闭MiniCluster和Spark Session,避免内存泄漏:
spark.stop() miniCluster.shutdown()
3. 调整Spark的序列化和存储配置
开启Kryo序列化可以大幅减少内存占用,同时调整存储内存比例避免缓存数据挤爆堆内存:
val spark = SparkSession.builder() .master("local[*]") .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") .config("spark.kryoserializer.buffer.max", "512m") .config("spark.memory.fraction", 0.5) // 降低存储内存占比,默认0.6,可根据情况调整 .getOrCreate()
4. 缩小测试数据集
如果你的测试用了太大的数据集,本地跑肯定容易OOM,建议用小批量的测试数据验证逻辑即可,单元测试重点是验证逻辑正确性,不是跑大数据量。
你提供的异常日志片段:
2018-03-18 16:01:34 INFO BlockManager:54 - Using org.apache.spark.storage.RandomBlockReplicationPolicy for block replication policy
2018-03-18 16:01:34 INFO BlockManagerMaster:54 - Registering BlockManager BlockManagerId(driver, 192.168.10.208, 57931, N...
内容的提问来源于stack exchange,提问作者chenatu
相关产品推荐
相关产品推荐

