机架感知
Hadoop组件具有机架感知功能。例如,HDFS通过机架感知来将块副本放在不同的机架上,从而提高容错。在群集中发生网络交换机故障或进行分区时,可提供数据可用性。
Hadoop主守护进程通过调用由配置文件指定的外部脚本或java类来获取群集从站的机架ID。使用java类或外部脚本进行拓扑,输出必须遵守java org.apache.hadoop.net.DNSToSwitchMapping接口。接口希望保持一一对应,并且“/ myrack / myhost”格式的拓扑信息,其中“/”是拓扑分隔符,“myrack”是机架标识符,“myhost”是个人主机。假设每个机架单/ 24个子网,可以使用“/192.168.100.0/192.168.100.5”格式作为唯一的机架主机拓扑映射。
要使用java类进行拓扑映射,类名由配置文件中的topology.node.switch.mapping.impl参数指定。一个示例NetworkTopology.java包含在hadoop分发中,可以由Hadoop管理员定制。使用Java类而不是外部脚本具有性能优势,因为当新的从节点注册自身时,Hadoop不需要分支外部进程。
如果实现一个外部脚本,将在配置文件中使用topology.script.file.name参数指定。与java类不同,外部拓扑脚本不包含在Hadoop分发中,需要由管理员提供。分派拓扑脚本时,Hadoop将向ARGV发送多个IP地址。发送到拓扑脚本的IP地址数量由net.topology.script.number.args控制,默认值为100.如果net.topology.script.number.args更改为1,则拓扑脚本将为每个由DataNodes和/或NodeMan提交的IP。
如果未设置topology.script.file.name或topology.node.switch.mapping.impl,则会为任何传递的IP地址返回机架ID“/ default-rack”。虽然这种行为似乎是可取的,但它可能会导致HDFS块副本的问题,因为默认行为是一个机架写入一个块副本(个人感觉翻译有问题,不过原文意思应该是多个块会写入不同的机架),并且无法这样做,但是会因为只有一个名为“/ default-rack”的机架。
另外一个配置设置是mapreduce.jobtracker.taskcache.levels,它决定了MapReduce将使用的缓存级别(在网络拓扑中)。因此,例如,如果默认值为2,则将构建两个级别的缓存 - 一个用于主机(主机 - >任务映射),另一个用于机架(机架 - >任务映射)。给我们一个一对一的映射“/ myrack / myhost”。
python示例
#!/usr/bin/python #这个脚本对物理环境做出假设。 #1)每个机架都是带有24个子网的第3层网络。#每个机架都拥有独立的交换机来连接到中心路由器, #因此每个机架都是独立的。 ## +-----------+ # |core router| # +-----------+ # / \ # +-----------+ +-----------+ # |rack switch| |rack switch| # +-----------+ +-----------+ # | data node | | data node | # +-----------+ +-----------+ # | data node | | data node | # +-----------+ +-----------+##2)拓扑脚本以IP地址列表作为输入,计算网络地址之后,将其作为输出,如'/ network_address / ip'。
import netaddr import sys sys.argv.pop(0)# 丢弃参数列表中的拓扑脚本名称,我们只需要它的ip地址 netmask = '255.255.255.0'# 将网络掩码设置为环境中所使用的值,例如/24 for ip in sys.argv:# 遍历datanode的ip列表 address = '{0}/{1}'.format(ip, netmask)# 格式化地址格式,使其符合'ip/netmask' 来使网络地址得以工作to make netaddr work try: network_address = netaddr.IPNetwork(address).network# calculate and print network address print "/{0}".format(network_address) except: print "/rack-unknown"# print catch-all value if unable to calculate network address/rack-unknown
bash示例
#!/bin/bash #这是一个bash示例,来展示这些脚本的样子 #假设我们将所有节点平铺在了单个交换机上,我们仍然可以自己做一个机架拓扑。 #这可能发生在我们的实验环境中,用有有限多个节点,如非托管交换机上的2-8个物理机器。 #这也适用于在同一物理机上运行的多个虚拟机。 #机器数量不重要,但是当没有网络拓扑时,我们可以自己做一个。
# # +----------+ +--------+ # |jobtracker| |datanode| # +----------+ +--------+ # \ / # +--------+ +--------+ +--------+ # |datanode|--| switch |--|datanode| # +--------+ +--------+ +--------+ # / \ # +--------+ +--------+ # |datanode| |namenode| # +--------+ +--------+#使用这种网络结构时,我们可以将每个主机视为一个机架。通过采取最后八个字节来完成的
#该实现,可以采用在datanode的IP中提取最后八个字节,并在之前加上“/rack-”字样。
#这样做的好处就是HDFS可以创建其“离架”块副本。
#1)'echo $ @'将所有ARGV值赋值给xargs。
#2)'xargs'将确保我们每行只打印一个argv值
#3)'awk'将分割点上的字段,并将最后一个字段附加到字符串'/rack-'后面。如果awk
#如果awk命令无法分割四个点,它仍然会打印'/rack-'最后一个字段值。
echo $ @ | xargs -n 1 | awk -F'。'{print“/ rack - ”$ NF}'