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
)
参考
- Hadoop ConnectionRefused https://cwiki.apache.org/confluence/display/HADOOP2/ConnectionRefused
- hadoop连接异常解决:ConnectionRefused Exception https://blog.csdn.net/sinat_34704593/article/details/84643531
- linux 查看并对外开放端口(防火墙拦截处理) https://www.cnblogs.com/blog-yuesheng521/p/7198829.html