Yarn SLS(Scheduler Load Simulator)模拟调度器

一、调度压力模拟器介绍

最近在调研Yarn调度性能问题,考虑到线上集群规模已达到5k+台,在线上环境实验是不太可行的,因此必须在线上有一套环境来验证调度器的性能,才能把有效的优化策略推广到线上环境。在线下环境搭建一套和线上规模相同的集群是不太合理的,需要耗费大量物理资源,成本耗费非常高。因此,需要有一个调度器的压力模拟器,在不需要大量物理机资源的条件下,能够模拟Yarn的调度过程。

Hadoop社区提供了开源调度器的压力模拟工具——Scheduler Load Simulator。

yarn调度压力模拟器

此图是基于美团对架构改造后的方案图,左侧是开源SLS的架构图,整个服务都在一个进程中,ResourceManager模块有一个用线程模拟的Scheduler,APPlication(APP)和NodeManager(NM)都是由线程模拟,作业资源申请和NM节点心跳都是采用方法调用。美团考虑到开源架构的性能问题,对架构进行了改造,从SLS中剥离Scheduler Wapper的模拟逻辑,用真实的ResourceManager代替,SLS仅模拟作业的资源申请和节点的心跳汇报。改造代码参考:YARN-7672
 
在对Yarn调度压力进行调研时,我们也是基于美团点评改造的方案,但SLS环境的使用基本是一致的,下面先对SLS展开介绍。

二、SLS使用

2.1 SLS介绍

SLS的功能实现主要在 /share/hadoop/tools/sls/ 中,SLS文件夹包括四个文件夹:bin,html,sample-conf,sample-data。

  • bin: 包含了sls的运行脚本,也就是启动命令
  • html:包含html、css、js文件,来实现实时追踪和web显示。
  • sample-conf:sls的配置文件
  • sample-data:提供了一个rumen trace的示例文件,可以用来作为sls的输入。

2.2 SLS参数

SLS默认参数在 /share/hadoop/tools/sls/sample-conf/sls-runner.xml 文件中。主要包括:任务提交参数、NM相关参数、APP相关参数、Container分配参数及运行指标参数(运行指标参数不单独介绍,用真实RM的健康指标即可)。

任务并发提交与任务并行运行相关参数:

yarn.sls.runner.pool.nm.size
模拟NodeManager的执行线程数量,越大执行效率越高,对RM的压力也越大。
 
yarn.sls.runner.pool.am.size
模拟ApplicationMaster的执行线程数量。
 
yarn.sls.am.parallel.max-num
在YARN上并行运行的最大App数量。
 
yarn.sls.nm.heartbeat.interval.ms
NodeManager心跳间隔时间,控制NodeManager向ResourceManager的心跳周期。
 
yarn.sls.am.submit.interval.ms
yarn.sls.am.submit.interval.count
此两个参数控制作业提交速度。当前值分别为每10秒钟提交100个作业。相当于每秒10个。
 
模拟资源相关参数:
yarn.sls.nm.memory.mb
yarn.sls.nm.vcores
每个NM节点模拟多少资源(内存与核心)。所有NM都是同样的资源数。
 
yarn.sls.container.memory.mb
yarn.sls.container.vcores
每个container申请多少资源(内存与核心)。所有container都是同样的资源数。

2.3 SLS环境运行

SLS支持两种类型的input files:rumen traces和sls traces。slsrun.sh脚本负责运行sls。
$ cd opt/cloudera/parcels/CDH/share/hadoop/tools/sls/
$ bin/slsrun.sh
    --input-rumen|--input-sls=<TRACE_FILE1,TRACE_FILE2,...>
    --output-dir=<SLS_SIMULATION_OUTPUT_DIRECTORY> [--nodes=<SLS_NODES_FILE>]
    [--track-jobs=<JOBID1,JOBID2,...>] [--print-simulation]

参数介绍: 

--input-rumen: 输入是rumen trace文件,示例为/share/hadoop/tools/sls/sample-data/2jobs2min-rumen-jh.json.

--input-sls: 输入是sls自己的格式文件,sls file。sls提供了一个工具来将rumen traces文件转换为sls trace:rumen2sls.sh(/share/hadoop/tools/sls/bin/)。

--output-dir: 输出监控数据和日志的目录

--nodes: 集群的拓扑结构,默认情况下,sls采用input json file中的拓扑,用户也可以指定一个新的拓扑结构。

--track-jobs: 在模拟器运行过程中跟踪的特定任务,由逗号分隔。

--print-simulation: 该参数决定了是否在模拟器运行前打印仿真信息,包括每个应用程序的节点、应用程序、任务和信息的数量。如果需要,只需要添加上该参数即可。

 
运行案例:sls-jobs.json为input-sls文件输入类型,sls-nodes.json是模拟的NM节点信息(运行rumen2sls.sh 脚本转换 rumen traces 生成)。
$ cd opt/cloudera/parcels/CDH/share/hadoop/tools/sls/
// sls traces输入
$ bin/slsrun.sh --input-sls=/root/cdh/sls/sls-jobs.json --nodes=/root/cdh/sls/sls-nodes.json --output-dir=/root/cdh/sls/output1 --print-simulation
// rumen traces输入
$ bin/slsrun.sh  --input-rumen=/opt/cloudera/parcels/CDH/share/hadoop/tools/sls/sample-data/2jobs2min-rumen-jh.json --nodes=/root/cdh/sls/sls-nodes.json --output-dir=/root/cdh/sls/output2

为了兼容 rumen traces 文件类型的输入,社区提供了一个脚本支持 rumen traces 转换为 sls traces,使用方式如下:

$ cd opt/cloudera/parcels/CDH/share/hadoop/tools/sls/
$ bin/rumen2sls.sh
    --rumen-file=<RUMEN_FILE>
    --output-dir=<SLS_OUTPUT_DIRECTORY>
    [--output-prefix=<SLS_FILE_PREFIX>]

运行案例:

$ bin/rumen2sls.sh --rumen-file=/opt/cloudera/parcels/CDH/share/hadoop/tools/sls/sample-data/2jobs2min-rumen-jh.json  --output-dir=/root/cdh/sls/

 运行sls环境过程中踩过的坑:https://www.cnblogs.com/walker-/p/13331255.html

三、大规模集群环境模拟

在真实的线上环境,APP数量和NM数量都是大规模量级的,因此我们需要自定义APP任务请求及NM节点规模,trace.big.json 是我们从线上环境导出的job信息,有6w+ jobs,nodes_10000.json 是人工构造的10k台NM节点信息。运行方式如下:
$ cd opt/cloudera/parcels/CDH/share/hadoop/tools/sls/
$ bin/slsrunForRealRM.sh  --input-rumen=/data/kwang/rumentrace/trace.big.json --nodes=/data1/kwang/nodes/nodes_10000.json  --output-dir=/data1/kwang/rumentrace/output2

3.1 如何生成大量jobs文件?

Hadoop社区提供了一个针对MR任务设计的日志分析工具Hadoop Rumen,SLS里可以用这个工具解析MR jobhistory server的日志,来生成模拟提交任务的数据。Hadoop Rumen的组件TraceBuilder(轨迹生成器)可以将MR历史日志转换成易解析的json格式文件。使用方式如下:
hadoop jar 
/opt/cloudera/parcels/CDH/share/hadoop/tools/lib/hadoop-rumen-2.6.0-cdh5.14.4.jar 
org.apache.hadoop.tools.rumen.TraceBuilder 
-recursive 
file:///var/lib/hadoop-hdfs/rumentrace/job-trace.json  # 输出trace文件
file:///var/lib/hadoop-hdfs/rumentrace/job-topology.json  # 输出NM的拓扑文件
hdfs://nameservice/user/history/logs/  # mr历史作业日志

3.2 如何构造10k规模NM节点?

NM节点主要是主机名和ip,10k节点信息我们通过一段java代码生成的。代码如下:
import java.util.Random;

public class RandomIp {

    public static String getRandomIp() {

        // ip范围
        int[][] range = {
                        {607649792, 608174079}, // 36.56.0.0-36.63.255.255
                        {1038614528, 1039007743}, // 61.232.0.0-61.237.255.255
                        {1783627776, 1784676351}, // 106.80.0.0-106.95.255.255
                        {2035023872, 2035154943}, // 121.76.0.0-121.77.255.255
                        {2078801920, 2079064063}, // 123.232.0.0-123.235.255.255
                        {-1950089216, -1948778497}, // 139.196.0.0-139.215.255.255
                        {-1425539072, -1425014785}, // 171.8.0.0-171.15.255.255
                        {-1236271104, -1235419137}, // 182.80.0.0-182.92.255.255
                        {-770113536, -768606209}, // 210.25.0.0-210.47.255.255
                        {-569376768, -564133889}, // 222.16.0.0-222.95.255.255
        };

        Random random = new Random();
        int index = random.nextInt(10);
        String ip = num2ip(range[index][0] + new Random().nextInt(range[index][1] - range[index][0]));
        return ip;
    }

    /*
     * 将十进制转换成IP地址
     */
    public static String num2ip(int ip) {
        int[] b = new int[4];
        String ipStr = "";
        b[0] = (int) ((ip >> 24) & 0xff);
        b[1] = (int) ((ip >> 16) & 0xff);
        b[2] = (int) ((ip >> 8) & 0xff);
        b[3] = (int) (ip & 0xff);
        ipStr = Integer.toString(b[0]) + "." + Integer.toString(b[1]) + "." + Integer.toString(b[2]) + "." + Integer.toString(b[3]);
        return ipStr;
    }

    public static void main(String[] args) {
        int count = 100;
        for (int i = 0; i < count; i++) {
            String randomIp = getRandomIp();
            System.out.println(randomIp);
        }
    }
}
View Code

注意:在将10k节点NM信息向RM注册时,需要在RM端允许未知host和ip信息向RM注册,避免被RM拒绝。

在yarn-site.xml的ResourceManager高级配置中添加如下配置,并允许所有未知节点向RM注册。之所以添加这个配置,是由于我们Hadoop集群是用Cloudera Manager维护的,如果不指定配置,Cloudera Manager则只允许维护的NM节点向RM注册,这个配置主要是设置RM的白名单,允许所有节点注册。
<property>
    <name>yarn.resourcemanager.nodes.include-path</name>
    <value>/etc/hadoop/myconf/nodes_allow.txt</value>
</property>

在active RM节点设置node白名单限制,允许所有节点向RM注册。

$ >/etc/hadoop/myconf/nodes_allow.txt      # 清空nodes_allow.txt文件,即允许所有节点向RM注册
$ su - yarn 'yarn rmadmin -refreshNodes'    # 刷新RM的Nodes列表信息
至此,我们线上的Yarn调度模拟环境已准备完毕,基本具备和线上规模同等的模拟环境。
 
 
【参考资料】
原文地址:https://www.cnblogs.com/lemonu/p/13330982.html