問題
在阿里雲上我部署了一個 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