今天现场在安装hadoop集群时说是启动报错,由于是新安装的集群,在处理问题时先按照手册进行了检查,没有发现任何配置问题。
于是在登陆服务器后,执行了一下hdfs zkfc -formatZK命令,发现报错如下
网上查找了半天,基本都是说zookeeper有问题或者没有执行hdfs namenode -format ;于是检查zookeeper状态,发现zookeeper正常;hdfs namenode -format命令也能够成功执行。
问题进行到此也没有太好的办法,于是想到了能否通过查看代码进行问题定位,首先在hdfs脚本中找到zkfc部分,发现对应的是如下java类
找到改类对应jar包,反编译查看了下代码, 发现报错代码部分
从代码可以发现nnId为null导致;于是查看了HAUtil.getNameNodeId(localNNConf, nsId)部分代码;代码中可以发现namenodeId可以从两个地方获取,其一是dfs.ha.namenode.id配置项,其二通过DFSUtil.getSuffixIDs方法获取
public static String getNameNodeId(Configuration conf, String nsId) {
String namenodeId = conf.getTrimmed("dfs.ha.namenode.id");
if (namenodeId != null) {
return namenodeId;
} else {
String[] suffixes = DFSUtil.getSuffixIDs(conf, "dfs.namenode.rpc-address", nsId, (String)null, DFSUtil.LOCAL_ADDRESS_MATCHER);
if (suffixes == null) {
String msg = "Configuration dfs.namenode.rpc-address must be suffixed with nameservice and namenode ID for HA configuration.";
throw new HadoopIllegalArgumentException(msg);
} else {
return suffixes[1];
}
}
}
dfs.ha.namenode.id配置项再我们自己的配置文件中是没有的,故可以排除此项,同时也有一个疑问,能否通过配置此项来规避当前出现的问题,但是这里我们并不知道dfs.ha.namenode.id代表的是什么。
那么只能先通过DFSUtil.getSuffixIDs方法看看返回的是什么;如下是关键部分代码
结合代码可以日志可以打印出nnId的内容,此时我们通过修改hdfs命令日志级别,在输出日志查看nnId的结果。最终发现nnId为hdfs-site.xml中的如下配置项
<property>
<name>dfs.ha.namenodes.runcdhInt</name>
<value>nn1,nn2</value>
</property>
既然有此配置项为什么无法获取呢?问题到此有遇见了瓶颈,暂时放下,尝试别的解决思路。
在hdfs-site.xml配置文件中增加dfs.ha.namenode.id,并将其值设置第一个主节点,即上图中的nn1。修改配置文件后继续执行hdfs namenode -format和hdfs zkfc -formatZK,这次报错没有了。尝试启动hdfs,结果namenode节点无法启动,报错端口占用,检查后发现无端口占用情况
查询资料发现此问题是双网ip问题导致,检查发现果然有两个ip,/etc/hosts当中配置的都是外网ip,将hosts中ip修改成内网ip,同时删除dfs.ha.namenode.id配置项;重新执行命令,到此问题解决,此记避免下次踩坑。