Article
spark-on-yarn内存分配
上次写了一篇关于配置参数是如何影响mapreduce的实际调度的参考:
- opts(yarn.app.mapreduce.am.command-opts、mapreduce.map.java.opts、mapreduce.reduce.java.opts)是实际运行程序是内存参数。
- memory(yarn.app.mapreduce.am.resource.mb、mapreduce.map.memory.mb、mapreduce.reduce.memory.mb)是用于ResourceManager计算集群资源使用和调度。
了解参数区别,就没有再深究task内存的问题了。
# 新问题-内存分配
这次又遇到内存问题:spark使用yarn-client的方式运行时,spark有memoryOverhead的设置,但是加了额外的内存后,再经过集群调度内存浪费严重,对于本来就小内存的集群来说完全无法接受。
- am默认是512加上384 overhead,也就是896m。但是调度后am分配内存资源为1024。
- executor默认是1024加上384,等于1408M。单调度后executor分配内存资源为2048。
[hive-on-spark-memory-allocate-0.png 图片]
从appmaster的日志可以看出来请求的内存大小是1408:
[hive-on-spark-memory-allocate-1.png 图片]
一个executor就浪费了500M,本来可以跑4个executor的但现在只能执行3个!
关于内存参数的具体含义查看官网: spark-on-yarn 和 yarn-default.xml
|| 参数 || 值
||:---------------------------------------:||:--------------------------------------------
|| spark.yarn.am.memory || 512m
|| spark.driver.memory || 1g
|| spark.yarn.executor.memoryOverhead || executorMemory * 0.10, with minimum of 384
|| spark.yarn.driver.memoryOverhead || driverMemory * 0.10, with minimum of 384
|| spark.yarn.am.memoryOverhead || AM memory * 0.10, with minimum of 384
|| yarn.nodemanager.resource.memory-mb || 8192
|| yarn.scheduler.minimum-allocation-mb || 1024
|| yarn.scheduler.maximum-allocation-mb || 8192
分配的内存看着像是 最小分配内存 的整数倍。把 yarn.scheduler.minimum-allocation-mb 修改为512,重启yarn再运行,executor的分配的内存果真减少到1536(512*3)。
[hive-on-spark-memory-allocate-3.png 图片]
同时 http://blog.javachen.com/2015/06/09/memory-in-spark-on-yarn.html 这篇文章也讲 在YARN中,Container申请的内存大小必须为yarn.scheduler.minimum-allocation-mb的整数倍 。我们不去猜,调试下调度代码,看看究竟是什么情况。
[hadoop@cu2 hadoop-2.6.3]$ sbin/yarn-daemon.sh stop resourcemanager
[hadoop@cu2 hadoop]$ grep "minimum-allocation-mb" -1 yarn-site.xml
<property>
<name>yarn.scheduler.minimum-allocation-mb</name><value>512</value>
</property>
[hadoop@cu2 hadoop-2.6.3]$ export YARN_RESOURCEMANAGER_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000"
[hadoop@cu2 hadoop-2.6.3]$ sbin/yarn-daemon.sh start resourcemanager
本地eclipse在 CapacityScheduler#allocate 打断点,然后跑任务:
hive> set hive.execution.engine=spark;
hive> select count(*) from t_ods_access_log2 where month=201512;
AppMaster内存分配:
[hive-on-spark-memory-allocate-appmaster.png 图片]
Executor内存分配:
[hive-on-spark-memory-allocate-executor.png 图片]
request进到allocate后,最终调用 DefaultResourceCalculator.normalize 重新计算了一遍请求需要的资源,把内存调整了。默认的DefaultResourceCalculator可以通过 capacity-scheduler.xml 的 yarn.scheduler.capacity.resource-calculator 来修改。
具体代码调度过程如下:
public Allocation allocate(ApplicationAttemptId applicationAttemptId,
List<ResourceRequest> ask, List<ContainerId> release,
List<String> blacklistAdditions, List<String> blacklistRemovals) {
...
// Sanity check
SchedulerUtils.normalizeRequests(
ask, getResourceCalculator(), getClusterResource(),
getMinimumResourceCapability(), maximumAllocation);
...
public static void normalizeRequest(
ResourceRequest ask,
ResourceCalculator resourceCalculator,
Resource clusterResource,
Resource minimumResource,
Resource maximumResource,
Resource incrementResource) {
Resource normalized =
Resources.normalize(
resourceCalculator, ask.getCapability(), minimumResource,
maximumResource, incrementResource);
ask.setCapability(normalized);
}
...
public static Resource normalize(
ResourceCalculator calculator, Resource lhs, Resource min,
Resource max, Resource increment) {
return calculator.normalize(lhs, min, max, increment);
}
...
public Resource normalize(Resource r, Resource minimumResource,
Resource maximumResource, Resource stepFactor) {
int normalizedMemory = Math.min(
roundUp(
Math.max(r.getMemory(), minimumResource.getMemory()),
stepFactor.getMemory()),
maximumResource.getMemory());
return Resources.createResource(normalizedMemory);
}
...
public static int roundUp(int a, int b) {
return divideAndCeil(a, b) * b;
}
# 小结
今天又重新认识一个yarn参数 yarn.scheduler.minimum-allocation-mb ,不仅仅是最小分配的内存,同时分配的资源也是minimum-allocation-mb的整数倍,还告诉我们 yarn.nodemanager.resource.memory-mb 也最好是minimum-allocation-mb的整数倍。
间接的学习了新的参数,可以通过 yarn.scheduler.capacity.resource-calculator 参数 来修改 CapacityScheduler 调度器的资源计算类。
–END
Related
Related posts
-
杀鸡焉用牛刀:DuckDB 正取代部分 Spark 场景
2026-02-16
-
基于对象存储的 Spark 数据读写实战:从末尾追加到任意更新
2025-10-28
-
认真的博客
2021-12-08
-
视频自动翻译
2018-08-25