【Hadoop】13-MapReduce用于配置的API

        MapReduce编程遵循一个特定的流程。首先写map函数和reduce函数,最好使用单元测试来确保函数的运行符合预期。然后,写一个驱动程序来运行作业,看这个驱动程序是否可以正确运行,就用本地IDE调试来找出问题根源。根据这些调试信息,可以通过扩展单元测试来覆盖这一测试用例,从而改进mapper或reducer,使其正确处理类似输入。
        一旦程序按预期通过小型数据集的测试,就可以考虑把他放到集群上运行了。当运行程序对整个数据进行测试的时候,可能会暴露更多的问题,这些问题可以像前面一样修复,即通过扩展测试用例及修改mapper或reducer函数的方式来应对新情况。在集群中调试程序很具有挑战性,我们来看一些常用的技术使其变得更简单一些。

        程序可以正确运行之后,如果想进行一些优化调整,首先需要执行一些标准检查,借此加快MapReduce程序的运行速度,然后再做任务剖析(task profiling)。分布式程序的分布并不简单,Hadoop提供了钩子(hook)来辅助这个分析过程。

      Hadoop中的组件是通过Hadoop自己的配置API来配置的。一个Configuration类的实例(可以在org.apache.hadoop.conf包中找到)代表配置属性及其取值的一个集合。每个属性由一个String来命名,而值的类型可以是多种类型之一,包括Java基本类型(如boolean、int、long和float)、其他有用的类型(如String、Class和java.io.File)及String集合。

        Configuration从资源(即使用简单结构定义名值对的XML文件)中读取其属性值。参见下面范例。

<?xml version="1.0"?>
<configuration>
  <property>
    <name>color</name>
    <value>yellow</value>
    <description>Color</description>
  </property>
  <property>
    <name>size</name>
    <value>10</value>
    <description>Size</description>
  </property>
  <property>
    <name>weight</name>
    <value>heavy</value>
    <final>true</final>
    <description>Weight</description>
  </property>
  <property>
    <name>size-weight</name>
    <value>${size},${weight}</value>
    <description>Size and weight</description>
  </property>
</configuration>

假定一个Configuration位于上面的文件中,我们可以通过如下代码访问其属性:

Configuration conf = new Configuration();
conf.addResource("configuratoin-1.xml");
assertThat(conf.get("color"), is("yellow"));
assertThat(conf.getInt("size", 0), is(10));
assertThat(conf.get("breadth", "wide"), is("wide"));

有这样几点需要注意:XML文件中不保存类型信息;取而代之的是属性在被读取的时候,可以被解释为指定的类型;此外,get()方法允许为XML文件中没有定义的属性指定默认值,正如这一代码中最后一行的breadth属性一样。

1.资源合并

        使用多个资源文件来定义一个Configuration时,事情变得有趣了。在Hadoop中,这用于分离(core-default.xml文件内部定义的)系统默认属性与(core-site.xml文件中定义的)位置相关(site-specific)的覆盖属性。下面范例中的文件定义了size属性和weight属性。

<?xml version="1.0"?>
<configuration>
  <property>
    <name>size</name>
    <value>12</value>
  </property>
  <property>
    <name>weight</name>
    <value>light</value>
  </property>
</configuration>

资源文件按顺序把上面两个配置文件信息添加到Configuration:

Configuration conf = new Configuration();
conf.addResource("configuration-1.xml");
conf.addResource("configuration-2.xml");

后来添加到资源的属性会覆盖(override)之前定义的属性。所以,size属性的取值来自于第二个配置文件configuration-2.xml:

assertThat(conf.getInt("size", 0), is(12));

不过,被标记为final的属性不能被后面的定义被覆盖。在第一个配置文件中,weight属性的final状态是true,因此,第二个配置文件中的覆盖设置失败,weight取值仍然是第一个配置文件中的heavy:

assertThat(conf.get("weight"), is("heavy"));

试图覆盖final属性通常意味着配置错误,所以最后会弹出警告消息来帮助进行故障诊断。一般来说,管理员将守护进程站点中的属性标记为final,表明他们不希望用户在客户端的配置文件或作业提交参数(job submission parameter)中有任何改动。

2.变量扩展

配置属性可以用其他属性或系统属性进行定义。例如,在第一个配置文件中的size-weight属性可以定义为${size}和${weight},而且这些属性是用配置文件中的值来扩展的:

assertThat(conf.get("size-weight"), is("12,heavy"));

系统属性的优先级高于资源文件中定义的属性:

System.setProperty("size", "14");
assertThat(conf.get("size-weight"), is("14 , heavy"));
 该特性特别适用于在命令行方式下用JVM参数-Dproperty=value来覆盖属性。

        注意,虽然配置属性可以通过系统属性来定义,但除非系统属性使用配置属性重新定义,否则,他们是无法通过配置API进行访问的。因此:

System.setProperty("size", "2");
assertThat(conf.get("length"), is((String) null));

猜你喜欢

转载自blog.csdn.net/shenchaohao12321/article/details/80300752