华为云MRS的yarn调度能力调优实践
发表于 2025/09/11
0
作者 | 陈兵
1 实践背景介绍
某银行业务系统使用华为云MRS服务,在资源节点达到两万个时,Yarn资源调度性能在鲲鹏服务器上为5100CPS(每秒启停容器数),在业界主流服务器上为8000CPS,鲲鹏服务器上Yarn的资源调度性能指标落后业界主流服务器约36.25%。需要将Yarn资源调度在鲲鹏环境的指标至少提升到业界主流服务器的水平。
环境信息
硬件环境信息
项目 |
配置信息 |
CPU型号 |
鲲鹏920 7265F处理器(64*4核) 鲲鹏920 7280Z处理器(80*4核) |
内存 |
64G*16 |
操作系统和软件环境信息
名称 |
版本 |
说明 |
openEuler |
22.03 SP2 |
测试环境OS |
SUSE |
15 |
测试环境OS |
Hadoop |
3.3.1_800 |
- |
Hadoop superior sls |
8.2.0 |
任务提交仿真器 |
测试场景
本项目中,使用Hadoop sls模拟资源节点和客户端提交任务等,以达到单机测试Yarn资源调度能力的目的。评判Yarn资源调度能力的指标为容器启动销毁的速度,指标单位为containers/s(CPS),通过influxdb采集CPS,grafana进行数据绘图。
不同处理器型号搭配不同版本的JDK达到的调优效果不同,调优效果请参见下文。
2 调优前性能数据
处理器型号 |
主频 |
Containers/s(CPS) |
鲲鹏920 7265F处理器 |
3.0GHz |
5100 |
鲲鹏920 7280Z处理器 |
2.9GHz |
5600 |
3 性能瓶颈分析
从下图所示的火焰图(arthas抓取)上看,Arm环境上没有明显的瓶颈点。
从CPU的利用率上看,多个线程在Arm环境的CPU利用率较低,从华为云那里了解到,“Superior Scheduler”、“SchedulerEventDispatcher”、“AsyncDispatcher”是Yarn资源调度主要的工作线程。而“Superior Scheduler”是实际进行资源调度的线程,其余工作线程与该线程都有一定依赖关系,同时该线程会存在周期性的休眠唤醒,所以分析可能是由于线程频繁切换上下文导致多个工作线程CPU利用率上不去。
通过查看GC日志,发现Arm环境的GC时间较长,分析可能是GC时间上对Arm环境资源调度存在影响,可以考虑更换GC算法。
由于这里是模拟的nm节点以及任务提交,不涉及磁盘IO以及网络交互,所以不必分析。
4 性能调优实践
4.1 鲲鹏920 7265F处理器
4.1.1 绑核
使用numactl命令对任意一个node进行绑核,这里以node0为例,剩余3个核不直接用numactl绑定,示例如下。
numactl --physcpubind=+4-63 --membind=0 ./run_simulator.sh 20m-25k-sls-trace_new.json_60s_1000queues sls-nodes-20000_60vcores_GH.json logs/
此处对0-3号核进行绑定,0号核其余应用也较为常用,不适用,然后将三个主要的工作线程绑定到1-3号核上,主要思想就是使用一个node中其余较为空闲的核进行线程绑定,线程绑核脚本示例如下,这里使用了“1”、“2”、“3”号核。绑核能带来约2.5k的CPS提升。
#!/bin/bash
#获取Java应用的进程ID
JAVA_PID="$1"
#等待Java应用启动
sleep5#根据实际情况调整等待时间
AsyncDispatcher=$(ps -T -p $JAVA_PID | grep "AsyncDispatcher" | awk '{print $2}')
SuperiorScheduler=$(ps -T -p $JAVA_PID | grep "Superior Schedu" | awk '{print $2}')
SchedulerEventDispatcher=$(ps -T -p $JAVA_PID | grep "SchedulerEventD" | awk '{print $2}')
taskset -pc 1 $AsyncDispatcher
taskset -pc 2 $SuperiorScheduler
taskset -pc 3 $SchedulerEventDispatcher
4.1.2 开启内存大页
-
查看内存大页的Hugepagesize。
cat /proc/meminfo
查询结果为2048KB。
-
编辑“/sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages”路径中对应页大小目录下的nr_hugepages文件,需要多少个大页就把数量写在该文件中,这里系统的大页size是2048KB,计算公式为:大页数量=堆内存/2048kB,可以适当设置的多一点。
-
-
Java使用内存大页时需要在JVM参数中增加LargePageSizeInBytes参数配置,LargePageSizeInBytes参数代表大页的页大小,需要与前面描述中的页大小,如:2048kB(2MB)保持一致。
该步骤使用内存大页对于CPS提升并没有明显效果,但是可以让CPS波动更小,请自主选择是否使用。
-XX:+UseLargePages -XX:LargePageSizeInBytes=2m
4.1.3 关闭CPU预取
开启CPU预取CPS会降低0.5k左右,因此需要关闭CPU预取。在BIOS中关闭CPU预取,操作步骤如下:
如何进入BIOS界面的具体操作请参见《TaiShan 服务器 BIOS 参数参考(鲲鹏920处理器)》中“进入BIOS界面”的相关内容。
4.1.4 开启性能模式
开启性能模式相较于不开启时,平均CPS会有100~200的提升。操作步骤如下。
4.1.5 调整GC参数
调优前JVM关于GC的参数配置为“-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=65”,经验证,使用G1等GC算法时,会降低CPS几百到一千不等。
调整CMSInitiatingOccupancyFraction参数时,也可以使CPS提升。经过多次测试,CMSInitiatingOccupancyFraction参数设置为80时,CPS提升最高,能提升约0.5~0.8k。
4.1.6 升级JDK版本(可选)
现网Yarn调度使用的JDK 8,将JDK 8升级为毕昇JDK 11后,能带来0.7~1.0k左右的CPS提升。
JVM参数JDK 8和JDK 11保持一致,参考“-Xms128G -Xmx128G -XX:NewSize=16G -XX:MaxNewSize=16G -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=80”。此处不能使用JDK 17,升级为JDK 17后效果达不到调优前的指标。
4.2 鲲鹏920 7280Z处理器
4.2.1 绑核
绑核方法与鲲鹏920 7265F处理器一样。鲲鹏920 7280Z处理器中node有80核,有需要可以修改下绑的核序号,不修改也没有多大影响。在使用JDK 8时能提升CPS 1.4k左右,使用JDK 11/17时能提升3.5k左右。
4.2.2 开启内存大页
设置方法请参见4.1.2-开启内存大页。开启内存大页并不能带来平均CPS的提升,但能很好的控制CPS的波动,尤其是在使用JDK升级后,波动抑制效果尤为明显。
4.2.3 调整内存刷新率
修改内存的刷新率,设置为1x Mode,在使用JDK 11/17版本时,能提升CPS 1.5k左右,使用JDK 8时影响不大。
4.2.4 开启性能模式
经测试,在鲲鹏920 7280Z处理器中,不开启性能模式,在使用JDK高版本时,会降低CPS约2k,因此建议开启性能模式。
4.2.5 升级JDK版本
使用JDK 8版本时,性能调优最多在7.5k左右,而更换成JDK 11或者JDK 17时,性能可以带来大幅度的提升。
-
更换JDK 11时,还是需要使用CMS GC算法,其余算法都会带来性能的降低,CMSInitiatingOccupancyFraction可以保持原先的65,或者修改为最新的80,影响不大。JDK 11的JVM参数配置建议为:“-Xms128G -Xmx128G -XX:NewSize=16G -XX:MaxNewSize=16G -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=80”。
-
使用JDK 17时,由于高低版本JDK存在一些包权限上的不同,需要在JVM参数中添加“--add-opens java.base/java.lang=ALL-UNNAMED”,否则应用无法启动,整体JVM参数配置建议为:“-Xms128G -XX:+UseLargePages -XX:LargePageSizeInBytes=2m -Xmx128G -XX:NewSize=16G -XX:MaxNewSize=16G -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M --add-opens java.base/java.lang=ALL-UNNAMED”。虽然JDK 17的性能更好,但是使用JDK 17时CPS的波动较大,需要斟酌使用。
4.2.6 使能SVE(仅限于JDK 11及以上可用)
在JDK 11及以上版本中,支持SVE,在本机型中,使用SVE能带来接近1k的CPS提升。只需要在JVM参数中添加“-XX:UseSVE=1”即可。但在实际的效果中看,JDK 11中使用SVE并没有明显提升,而在JDK 17中使用则可以带来1k左右的提升。
5 调优实践效果
-
鲲鹏920 7265F处理器中,使用以上调优方法在JDK 8时CPS达到8.0~8.3k,提升幅度达到60%;在JDK 11时CPS达到9.0k左右,提升幅度达到76%。
-
鲲鹏920 7280Z处理器中使用了进程绑核+线程单独绑核;内存大页;开启性能模式;调整内存刷新率;JDK版本升级;SVE使能。由于使用JDK 8时仅有绑核有明显效果,其余步骤仅在JDK 11/17上面效果明显。调优方法可能存在一定的关联性,如果单独使用可能没法带来描述那么大的收益,如内存刷新率在JDK 8就没有什么效果。且各个调优步骤之间的收益存在一定的重叠,不能单纯进行收益相加计算总收益。
鲲鹏920 7280Z处理器中,调优前CPS可以达到5600。使用JDK 8时,CPS只能调优到7.5k左右,更换JDK 11时,使用以上调优手段,CPS达到14.3~14.5k左右。
处理器型号 |
JDK 8 |
JDK 11 |
JDK 17 |
鲲鹏920 7265F处理器 |
8.0~8.3k |
9.0k |
- |
鲲鹏920 7280Z处理器 |
- |
15k |
16k |
6 故障排除
6.1 taskset线程绑核无效
问题现象描述
numactl进行node0(0-63核)进程绑核后,再使用taskset对线程进行单独绑核并没有效果,线程绑定的核仍然存在漂移。
关键过程、根本原因分析
由于taskset对线程绑定的核序号在numactl绑核的序号范围内,怀疑两个程序存在一定的优先级,导致taskset绑核失败。
结论、解决方案及效果
numactl绑核时,仅使用4-63号核,剩余几个核不绑定,再使用taskset将工作线程绑定在1-3号核上,执行程序发现性能得到提升,核也绑定成功。
6.2 perf制作火焰图失败
问题现象描述
使用perf record对Java应用进行分析时,抓取的数据文件总是打开存在报错,而且看不到实际的Java工作内容,并且perf在抓取信息时,还会很大程度干扰应用的执行,进而无法制作火焰图。
关键过程、根本原因分析
查看perf抓取的信息都是底层so库之类的信息,怀疑perf本身对Java虚拟机内部的信息抓取支持不是很好,考虑更换可以抓取Java虚拟机内部信息的工具。
结论、解决方案及效果
使用Arthas工具,可以准确抓取Java进程信息,制作出火焰图。
6.3 Java应用在JDK 17环境报错
问题现象描述
Yarn调度器原先使用的是JDK 8,使用JDK 11不会报错,但是更换JDK 17后存在报错。报错信息如下:
关键过程、根本原因分析
从JDK 9开始,Java引入了模块系统,限制了对内部API的访问。而JDK 11对于API的限制还没有特别严格,JDK 17开始限制极其严格。
结论、解决方案及效果
对JVM增加参数“--add-opens java.base/java.lang=ALL-UNNAMED”,成功在JDK 17环境运行应用。