• 6.2.2 辅助类GenericOptionsParser,Tool和ToolRunner深入解析


       辅助类GenericOptionsParser,Tool和ToolRunner

    (1)为什么要用ToolRunner

    将MapReduce Job配置参数写到java代码里,一旦变更意味着修改java文件源码、编译、打包、部署一连串事情。当MapReduce 依赖配置文件的时候,你需要手工编写java代码使用DistributedCache将其上传到HDFS中,以便map和reduce函数可以读取。:当你的map或reduce 函数依赖第三方jar文件时,你在命令行中使用”-libjars”参数指定依赖jar包时,但根本没生效。Hadoop有个可以GenericOptionsParser是一个类,用来解释常用的Hadoop命令行选项,通过简单的命令行参数来实现这样的功能,为Configuration对象设置相应的取值。通常不直接使用GenericOptionsParser,更方便的方式是:实现Tool接口,通过ToolRunner来运行应用程序,ToolRunner内部调用GenericOptionsParser来解析命令行。设置Configuration对象。

    (2)使用ToolRunner步骤

    自定义一个ToolRunner类ToolRunnerDemo类,继承Configured类,实现Tool接口,实现Tool的run(String [] args)方法,并在main函数中调用ToolRunner. run(Tool tool, String[] args)静态方法。Run方法内部创建GenericOptionsParser parser = new GenericOptionsParser(conf, args);调用GenericOptionsParser解析命令行参数,解析完之后将参数设置到Configuration对象中。

    1)创建ToolRunnerDemo对象

    package org.jediael.hadoopdemo.toolrunnerdemo;

    import java.util.Map.Entry;

    import org.apache.hadoop.conf.Configuration;

    import org.apache.hadoop.conf.Configured;

    import org.apache.hadoop.util.Tool;

    import org.apache.hadoop.util.ToolRunner;

    public class ToolRunnerDemo extends Configured implements Tool {

           static {

                  //Configuration.addDefaultResource("hdfs-default.xml");

                  //Configuration.addDefaultResource("hdfs-site.xml");

                  //Configuration.addDefaultResource("mapred-default.xml");

                  //Configuration.addDefaultResource("mapred-site.xml");

           }

           @Override

           public int run(String[] args) throws Exception {

                  Configuration conf = getConf();

                  for (Entry<String, String> entry : conf) {

                         System.out.printf("%s=%s ", entry.getKey(), entry.getValue());

                  }

                  return 0;

           }

           public static void main(String[] args) throws Exception {

                  int exitCode = ToolRunner.run(new ToolRunnerDemo(), args);//ToolRunnerDemo对象实现了Tool接口,形参传入对象引用,在调用tool.run()方法,实际是调用ToolRunner重写的run方法

                  System.exit(exitCode);

           }

    }

    Configurable接口只有两个函数,获取设置Configuration对象

    package org.apache.hadoop.conf;

    public interface Configurable {

      void setConf(Configuration conf);

      Configuration getConf();

    }

    Configred类实现了Configurable接口

    package org.apache.hadoop.conf;

    public class Configured implements Configurable {

      private Configuration conf;

      public Configured() {

        this(null);

      }

      public Configured(Configuration conf) {

        setConf(conf);

      }

      public void setConf(Configuration conf) {

        this.conf = conf;

      }

      public Configuration getConf() {

        return conf;

      }

    }

    2)ToolRunner.run()函数内部创建GenericOptionsParser对象

    public static int run(Configuration conf, Tool tool, String[] args) throws Exception {

            if (conf == null) {

                conf = new Configuration();

            }

            GenericOptionsParser parser = new GenericOptionsParser(conf, args);

            tool.setConf(conf);

            String[] toolArgs = parser.getRemainingArgs();

            return tool.run(toolArgs);

        }

    3)GenericOptionsParser构造函数1调用构造函数2,构造函数2调用解析函数parseGeneralOptions

    public GenericOptionsParser(Options opts, String[] args) throws IOException {

            this(new Configuration(), opts, args);

        }//构造函数1

        public GenericOptionsParser(Configuration conf, Options options, String[] args) throws IOException {

            this.parseGeneralOptions(options, conf, args);

            this.conf = conf;

    }//构造函数2

    4)parseGeneralOptions先调用解析函数parser.parse解析命令行,然后再用函数this.processGeneralOptions()执行命令。

    private void parseGeneralOptions(Options opts, Configuration conf, String[] args) throws IOException {

            opts = buildGeneralOptions(opts);

            GnuParser parser = new GnuParser();

            try {

                this.commandLine = parser.parse(opts, this.preProcessForWindows(args), true);

                this.processGeneralOptions(conf, this.commandLine);

            } catch (ParseException var7) {

                LOG.warn("options parsing failed: " + var7.getMessage());

                HelpFormatter formatter = new HelpFormatter();

                formatter.printHelp("general options are: ", opts);

            }

    }

    5)processGeneralOptions函数内部会根据不同的命令选项:fs、jt、conf、libjars、files、archives进行设置。

    private void processGeneralOptions(Configuration conf, CommandLine line) throws IOException {

    //设置默认的文件系统

            if (line.hasOption("fs")) {

                FileSystem.setDefaultUri(conf, line.getOptionValue("fs"));

            }

    //设置jobtracker服务ip地址和端口,用于监听并接收来自各个TaskTracker发送的心跳信息,包括资源使用情况和任务运行情况等信息。

            String fileName;

            if (line.hasOption("jt")) {

                fileName = line.getOptionValue("jt");

                if (fileName.equalsIgnoreCase("local")) {

                    conf.set("mapreduce.framework.name", fileName);

                }

                conf.set("yarn.resourcemanager.address", fileName, "from -jt command line option");

            }

    //添加新的配置文件

            String[] arr$;

            int len$;

            int i$;

            String prop;

            String[] property;

            if (line.hasOption("conf")) {

                property = line.getOptionValues("conf");

                arr$ = property;

                len$ = property.length;

                for(i$ = 0; i$ < len$; ++i$) {

                    prop = arr$[i$];

                    conf.addResource(new Path(prop));

                }

            }

    //从本地文件系统中复制指定的jar包到jobtracker使用的共享文件系统中,添加到mapreduce任务路径,这个选项是一个很有用放入方法来添加任务的依赖jar包。

            if (line.hasOption("libjars")) {

                conf.set("tmpjars", this.validateFiles(line.getOptionValue("libjars"), conf), "from -libjars command line option");

                URL[] libjars = getLibJars(conf);

                if (libjars != null && libjars.length > 0) {

                    conf.setClassLoader(new URLClassLoader(libjars, conf.getClassLoader()));

                    Thread.currentThread().setContextClassLoader(new URLClassLoader(libjars, Thread.currentThread().getContextClassLoader()));

                }

            }

    //从本地文件系统中复制指定的文件到jobtracker使用的共享文件系统中,使他们能够被mapreduce任务使用

            if (line.hasOption("files")) {

                conf.set("tmpfiles", this.validateFiles(line.getOptionValue("files"), conf), "from -files command line option");

            }

    //从本地文件系统中复制指定的档案到jobtracker使用的共享文件系统中,使他们能够被mapreduce任务使用。

            if (line.hasOption("archives")) {

                conf.set("tmparchives", this.validateFiles(line.getOptionValue("archives"), conf), "from -archives command line option");

            }

    //给属性设置属性值

            if (line.hasOption('D')) {

                property = line.getOptionValues('D');

                arr$ = property;

                len$ = property.length;

                for(i$ = 0; i$ < len$; ++i$) {

                    prop = arr$[i$];

                    String[] keyval = prop.split("=", 2);

                    if (keyval.length == 2) {

                        conf.set(keyval[0], keyval[1], "from command line");

                    }

                }

            }

            conf.setBoolean("mapreduce.client.genericoptionsparser.used", true);

            if (line.hasOption("tokenCacheFile")) {

                fileName = line.getOptionValue("tokenCacheFile");

                FileSystem localFs = FileSystem.getLocal(conf);

                Path p = localFs.makeQualified(new Path(fileName));

                if (!localFs.exists(p)) {

                    throw new FileNotFoundException("File " + fileName + " does not exist.");

                }

                if (LOG.isDebugEnabled()) {

                    LOG.debug("setting conf tokensFile: " + fileName);

                }

                UserGroupInformation.getCurrentUser().addCredentials(Credentials.readTokenStorageFile(p, conf));

                conf.set("mapreduce.job.credentials.json", p.toString(), "from -tokenCacheFile command line option");

            }

        }

    6)设置好配置之后,所有的命令行都解析执行,参数都添加到了Configuration对象之中,接下来就可以获取这些参数。

    在第2)步的ToolRunner的run函数中

     public static int run(Configuration conf, Tool tool, String[] args) throws Exception {

            if (conf == null) {

                conf = new Configuration();

            }

            GenericOptionsParser parser = new GenericOptionsParser(conf, args);

            tool.setConf(conf);

            String[] toolArgs = parser.getRemainingArgs();

            return tool.run(toolArgs);

        }

    parser.getRemainingArgs();获取的实际上是第4)步中解析的命令行参数

    public String[] getRemainingArgs() {

            return this.commandLine == null ? new String[0] : this.commandLine.getArgs();

        }

    7)调用tool接口的run方法,实际是调用ToolRunnerDemo重写的run方法。因为ToolRunnerDemo对象实现了Tool接口,ToolRunner.run函数形参传入ToolRunnerDemo对象引用,在调用tool.run()方法, 实际是调用ToolRunnerDemo重写的run方法。这个run方法的作用是打印所有的配置项。

    @Override

           public int run(String[] args) throws Exception {

                  Configuration conf = getConf();

                  for (Entry<String, String> entry : conf) {//输出所有的属性值

                         System.out.printf("%s=%s ", entry.getKey(), entry.getValue());

                  }

                  return 0;

           }

    (3)使用ToolRunnerDemo设置hadoop参数调用实例

    1)使用ToolRunnerDemo输出所有配置属性

    [root@jediael project]#hadoop jar toolrunnerdemo.jar org.jediael.hadoopdemo.toolrunnerdemo.ToolRunnerDemo

    io.seqfile.compress.blocksize=1000000 

    keep.failed.task.files=false 

    mapred.disk.healthChecker.interval=60000 

    dfs.df.interval=60000 

    dfs.datanode.failed.volumes.tolerated=0 

    mapreduce.reduce.input.limit=-1 

    mapred.task.tracker.http.address=0.0.0.0:50060 

    mapred.used.genericoptionsparser=true 

    mapred.userlog.retain.hours=24 

    dfs.max.objects=0 

    mapred.jobtracker.jobSchedulable=org.apache.hadoop.mapred.JobSchedulable 

    mapred.local.dir.minspacestart=0 

    hadoop.native.lib=true

    2)通过-D指定新的参数,-D设置参数color为yello,grep查看设置属性

    [root@jediael project]# hadoop org.jediael.hadoopdemo.toolrunnerdemo.ToolRunnerDemo -D color=yello | grep color

    color=yello

    3)通过-conf增加新的配置文件,-conf用于添加配置文件,wc命令用于查看配置数量。

    hadoop jar toolrunnerdemo.jar org.jediael.hadoopdemo.toolrunnerdemo.ToolRunnerDemo-conf /opt/jediael/hadoop-1.2.0/conf/mapred-site.xml | wc 

        68 68 3028

    其中mapred-site.xml的内容如下:

    <?xml version="1.0"?>

    <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

    <configuration> 

         <property>

             <name>mapred.job.tracker</name>

             <value>localhost:9001</value>

         </property>

    </configuration>

    (4)ToolRunner使用汇总

    -D color=yello

    -D设置参数color为yello,grep查看设置属性

    -conf conf/mapred-site.xml

    -conf用于添加配置文件

    -fs uri

    //设置文件系统为uri指定的路径,等同-D fs.default.FS=url

    -jt 10.21.34.11:3800

    //hadoop1中用于设置jobtracker的ip地址和端口,用于监听并接收来自各个TaskTracker发送的心跳信息,包括资源使用情况和任务运行情况等信息。hadoop2中用于指定YARN资源管理器地址。等同-D yarn.resourcemanager.address= 10.21.34.11:3800.

    -files file1,file2

    从本地文件系统中复制指定的文件到jobtracker使用的共享文件系统中,使他们能够被mapreduce任务使用

    -libjars jars1,jars2

    从本地文件系统中复制指定的jar包到jobtracker使用的共享文件系统中,添加到mapreduce任务路径,这个选项是一个很有用放入方法来添加任务的依赖jar包。

    -archives archive1,archive2

    从本地文件系统中复制指定的档案到jobtracker使用的共享文件系统中,使他们能够被mapreduce任务使用。

    参考文献:

    https://blog.csdn.net/xin15200793067/article/details/12623797

    https://blog.csdn.net/jediael_lu/article/details/38751885

    https://blog.csdn.net/tototuzuoquan/article/details/72856761

    自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:

    https://www.cnblogs.com/bclshuai/p/11380657.html

  • 相关阅读:
    今天过节提前下班
    作控件也挺郁闷啊!
    使用Windows XP的主题
    这几天关心加密的人很多
    多普达515,好爽啊!
    515看电影
    我要定计划
    龙芯II发布了,好事儿!
    转:关于星际与XP的结对编程
    昨天参加了一个微软的会
  • 原文地址:https://www.cnblogs.com/bclshuai/p/11884186.html
Copyright © 2020-2023  润新知