hadoop配置机架感知html
接着上一篇来讲。上篇说了hadoop网络拓扑的构成及其相应的网络位置转换方式,本篇主要讲经过两种方式来配置机架感知。一种是经过配置一个脚原本进行映射;另外一种是经过实现DNSToSwitchMapping接口的resolve()方法来完成网络位置的映射。java
hadoop自身是没有机架感知能力的,必须经过人为的设定来达到这个目的。在FSNamesystem类中的resolveNetworkLocation()方法负载进行网络位置的转换。其中dnsToSwitchMapping变量表明了完成具体转换工做的类,其值以下: node
1 this.dnsToSwitchMapping = ReflectionUtils.newInstance(2 conf.getClass("topology.node.switch.mapping.impl", ScriptBasedMapping.class,3 DNSToSwitchMapping.class), conf);
也就是说dnsToSwitchMapping的值由“core-site.xml”配置文件中的"topology.node.switch.mapping.impl"参数指定。默认值为ScriptBasedMapping,也就是经过读提早写好的脚本文件来进行网络位置映射的。但若是这个脚本没有配置的话,那就使用默认值“default-rack”做为全部结点的网络位置。shell
下面就先说说第一种配置机架感知的方法,使用脚原本完成网络位置的映射。这须要在“core-site.xml”配置文件中的“topology.script.file.name”参数中指定脚本文件的位置。在wiki上找到一个官方的配置脚本,能够参考一下。首先是shell脚本:apache
1 HADOOP_CONF=/etc/hadoop/conf 2 3 while [ $# -gt 0 ] ; do //$#表明执行命令时输入的参数个数 4 nodeArg=$1 5 exec< ${HADOOP_CONF}/topology.data //读入文件 6 result="" 7 while read line ; do //循环遍历文件内容 8 ar=( $line ) 9 if [ "${ar[0]}" = "$nodeArg" ] ; then10 result="${ar[1]}"11 fi12 done 13 shift 14 if [ -z "$result" ] ; then15 echo -n "/default/rack "16 else17 echo -n "$result "18 fi19 done
topology.data文件格式以下:网络
tt156 /dc1/rack1 tt163 /dc1/rack1 tt164 /dc1/rack2 tt165 /dc1/rack210.32.11.156 /dc1/rack110.32.11.163 /dc1/rack110.32.11.164 /dc1/rack210.32.11.165 /dc1/rack2
我是把原来topology.data文件内容改了下,把hostname也添加进去了,这样保证正确性。由于JobTracker是经过hostname进行映射的。app
网上也有用Python脚本和C语言写的,但我对Python不是很熟,因此在这里就不说了。总结上边的内容,能够知道,无论用什么脚原本写,最重要的就是接收参数,完成网络位置映射并将结果输出。这样系统就可以接收到合适结果。jvm
第二种配置机架感知的方法是经过实现DNSToSwitchMapping接口,重写resolve()方法完成的。这就须要本身写个java类来完成映射了。而后在“core-site.xml”配置文件中的“topology.node.switch.mapping.impl”指定本身的实现类。这样的话,在进行网络位置解析的时候,就会调用本身类中的resolve()方法来完成转换了。我写的比较简单,能完成功能就好,代码以下(大神飞过):ide
1 public class MyResolveNetworkTopology implements DNSToSwitchMapping { 2 3 private String[] hostnameLists = {"tt156", "tt163", "tt164", "tt165"}; 4 private String[] ipLists = {"10.32.11.156", "10.32.11.163", "10.32.11.164", "10.32.11.165"}; 5 private String[] resolvedLists = {"/dc1/rack1", "/dc1/rack1", "/dc1/rack2", "/dc1/rack2"}; 6 7 @Override 8 public List<String> resolve(List<String> names) { 9 names = NetUtils.normalizeHostNames(names);10 11 List <String> result = new ArrayList<String>(names.size());12 if (names.isEmpty()) {13 return result;14 }15 16 for (int i = 0; i < names.size(); i++) {17 String name = names.get(i);18 for(int j = 0; j < hostnameLists.length; j++){19 if(name.equals(hostnameLists[j])) {20 result.add(resolvedLists[j]);21 } else if(name.equals(ipLists[j])) {22 result.add(resolvedLists[j]);23 }24 }25 }26 return result;27 }28 }
我把这个自定义的MyResolveNetworkTopology类放在了core包的org.apache.hadoop.net目录下。因此在“core-site.xml”文件中的配置以下: oop
<property> <name>topology.node.switch.mapping.impl</name> <value>org.apache.hadoop.net.MyResolveNetworkTopology</value> <description> The default implementation of the DNSToSwitchMapping. It invokes a script specified in topology.script.file.name to resolve node names. If the value for topology.script.file.name is not set, the default value of DEFAULT_RACK is returned for all node names. </description></property>
以上两种方法在配置完成后,会在NameNode和JobTracker的log中打印出以下信息:
2015-05-26 20:47:20,665 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /dc1/rack1/tt163 2015-05-26 20:47:20,689 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /dc1/rack1/tt156 .......
这就说明机架感知配置成功了。
总结一下以上两种方式。经过脚本配置的方式,灵活性很高,可是执行效率较低。由于系统要从jvm转到shell去执行;java类的方式性能较高,可是编译以后就没法改变了,因此灵活程度较低。因此要根据具体状况来选择策略.