经常会有这样的需求:

在MR程序中,map,reduce等方法中需要传入一些外部参数,比如我们要编写MR程序访问页面访问的Top n,其中的n就是我们需要传入的外部参数。但是,map和reduce等方法都是由MapTask和RedcueTask调用的,我们编程的时候是从父类继承方法,然后override来实现我们的逻辑。所以方法的标签是不能改变的,那么,这个外部参数又该用怎样的方式传递给这些方法呢?

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

那就是利用方法的一个参数,context来传递。

先来看下这个,

Configuration conf = new Configuration();
conf.setInt("topn", 6);
Job job = Job.getInstance(conf);

这是我们编写job提交程序时的一般做法,这句话的含义是创建conf对象,对job运行时的一些参数进行配置,把该conf对象封装到job对象中,job运行的时候就会去读conf中的配置信息,conf对象可以通过Context对象获取。这样反过来我们就可以为map和reduce等方法获得外部参数啦:map方法的形参包括context对象,方法执行时通过MapTask传入该参数值,然后通过context对象我们可以获取job的conf对象,如果在conf中封装了我们要传入的外部参数,那么就可以反向获得这个参数了。

在map或reduce方法中,通过以下方法可以得到配置参数值:

 Configuration conf = context.getConfiguration();
 int topn = conf.getInt(conf.get("topn", 5));//“topn”为要获取的参数的name,5为该参数的默认值

这里通过context获得的conf对象,是我们项目运行的通用配置信息(其实它的作用大致相当于我们在进行集群配置时修改的core-site.xml和hdfs.xml)。那么我们又该如何把topn的值放到conf对象里去呢?

在jobsubmitter中,conf对象创建后,通过set方法封装参数值。

Configuration conf = new Configuration();
conf.setInt("topn", 6);

 

补充:

其实,这里也是把参数值写死到代码中,那么我们怎么不把这个参数在代码中写死呢?比如我开始想求top5,现在想求top3。

方法一:利用main方法在运行时传入参数。

public class PageCountJobSubmitter {

    public static void main(String[] args)
            throws IOException, ClassNotFoundException, InterruptedException {

        Configuration conf = new Configuration();
        conf.setInt("topn", args[0]);
        Job job = Job.getInstance(conf);
              ……
    }
}

方法二:通过属性配置文件获取参数

public class PageCountJobSubmitter {

    public static void main(String[] args)
            throws IOException, ClassNotFoundException, InterruptedException {

        Configuration conf = new Configuration();
        Properties properties = new Properties();
        properties.load(PageCountJobSubmitter.class.getClassLoader().
                getResourceAsStream("I:\\CodePractice\\flowcount\\Topn\\src\\main\\resources\\topn.proterpties"));
        conf.setInt("topn", Integer.parseInt(properties.getProperty("topn")));

        ……
    }

}

 

方法三:通过classpath下的xml文件加载

public class PageCountJobSubmitter {

    public static void main(String[] args)
            throws IOException, ClassNotFoundException, InterruptedException {

        Configuration conf = new Configuration();
/*
        Properties properties = new Properties();
        properties.load(PageCountJobSubmitter.class.getClassLoader().
                getResourceAsStream("topn.proterpties"));
        conf.setInt("topn", Integer.parseInt(properties.getProperty("topn")));
*/
        conf.addResource(new Path("I:\\CodePractice\\" +
                "flowcount\\Topn\\src\\main\\java\\topn.xml"));//这种绝对路径不太优雅。。。


    }

}

 

 

context里存储项目运行的上下文参数,

方法一:

 

方法二:

方法三:

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄