Hadoop异常解决:本地连接阿里云HDFS服务Connection refused

问题

在阿里云上我部署了一个 Single Cluster 的 HDFS,使用hadoop fs -ls /查看没有问题。

然后,在本地我跑了一个Java程序,想要连接阿里云的 HDFS 并进行基本操作。但是运行的时候报错了,关键信息如下:

java.net.ConnectException: Connection refused

端口号

首先,根据经验,我猜想是服务器的端口号没有开放。

收集信息:

  • NameNode配置的端口号是9000。
  • Java程序中连接的路径是:hdfs://133.444.555.666:9000。端口号也是9000。

打开阿里云的安全组,查看入网方向的规则:

授权策略	      协议类型	    	端口范围		授权类型(全部)       授权对象
允许	      自定义 TCP		9090/9090	IPv4地址段访问	      0.0.0.0/0
允许	      自定义 TCP		50070/50070	IPv4地址段访问	      0.0.0.0/0	
允许	      自定义 TCP		3389/3389	IPv4地址段访问	      0.0.0.0/0
允许	      全部 ICMP(IPv4)	-1/-1		IPv4地址段访问	      0.0.0.0/0
允许	      自定义 TCP		22/22		IPv4地址段访问	      0.0.0.0/0

发现真的没有配置,于是把9000端口加上了。

重启试了一遍,发现还是不行。

防火墙 - 本机

然后,我猜想是本机的防火墙问题。

我把本地 Windows 的防火墙关掉了再试了一遍,还是不行。

防火墙 - 服务器

然后,我猜想是服务器的防火墙问题。

使用iptables命令查看,发现并没有设置防火墙。

# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

为了保险起见,我还是把 ACCEPT 的端口号加上了:

iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 9000 -j ACCEPT
iptables -I INPUT -m state --state NEW -m udp -p udp --dport 9000 -j ACCEPT

参考 -> 阿里云服务器关于端口开放的坑 https://blog.csdn.net/qq_40855366/article/details/99011978

本地排查

接着,我从客户端 ping 服务器上的端口。

# ssh 端口,成功
telnet 133.444.555.666 22

# hdfs 网页监控端口,成功
telnet 133.444.555.666 50070

# hdfs NameNode 端口,失败
telnet 133.444.555.666 9000

说明:首先本机可以 ping 到 aliyun 服务器;其次,本机可以 ping 到 hdfs 的一个服务端口;那我基本可以确定,问题出在服务器端,客户端是没有问题的。

服务器排查

到这里,我又猜想是NameNode起的有问题,或者不在这个端口上。

Check 1:使用jps,能看到NameNode这个进程。如下:

# jps
18406 DataNode
18264 NameNode

Check 2:查看 HDFS 的 log,能看到NameNode起在了这个端口。如下:

INFO org.apache.hadoop.hdfs.server.NameNode.NameNode: fs.defaultFS is hdfs://hadoop000:9000

Check 3:使用lsof查看使用中的端口。能看到9000确实起了NameNode并且在监听。如下:

# lsof -i:9000
COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
java    18264 root  207u  IPv4 2030078      0t0  TCP *:cslistener (LISTEN)
java    18264 root  217u  IPv4 2031428      0t0  TCP localhost:cslistener->localhost:49018 (ESTABLISHED)
java    18406 root  229u  IPv4 2031421      0t0  TCP localhost:49018->localhost:cslistener (ESTABLISHED)

Check 4:使用netstat查看网络连接的具体信息。如下:

# netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:50070           0.0.0.0:*               LISTEN      14724/java
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      987/sshd
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      14724/java
tcp        0      0 127.0.0.1:39849         0.0.0.0:*               LISTEN      14865/java

这里其实能看到问题,Local Address为什么是127.0.0.1:9000?相当于NameNode“起”在了127.0.0.1这个IP上,外面进来的request,应该走的是0.0.0.0这个IP,所以连接不上。

Check 5:为了进一步验证,在服务器端 ping 内网的端口。如下:

# 失败
telnet 199.888.777.666 9000

说明:我在服务器端 ping 内网的 HDFS 服务失败,说明 HDFS 服务本身起错了(IP地址不对)。结论和上面一样。

修改

因为我的 Hadoop 配置文件里面的路径使用的是 hostname 格式:hadoop000,所以应该是域名解析得不对。

打开/etc/hosts,做出如下修改:

127.0.0.1       hadoop000       hadoop000

变成 ->

0.0.0.0      hadoop000       hadoop000

(注:更好的方案是改成内网IP,这样更方便安全一些)

重启,再试就好了。

总结

解决类似问题,思路如下:

  • 服务器端,服务是否正确起来了 -> jps + 看log
  • 网络通信问题
  • 客户端,本地代码调用是否正确

排查网络通信问题,最主要的一个命令是telnet,通过 ping 各个 HOSTNAME/IP + PORT,查看网络链路是否通畅。

client_side: ping server_service (外网IP)
server_side: ping server_service (外网IP + 内网IP)

如果不通畅,可能是如下的问题:

  • 防火墙(客户端 + 服务器端)
  • 其它拦截措施(阿里云安全组规则)
  • 域名解析是否正确(HOSTNAME <-> IP
  • 端口绑定是否正确(PORT <-> HOSTNAME/IP

参考

posted @ 2020-10-28 14:10  MaxStack  阅读(1532)  评论(0编辑  收藏  举报