1. 程式人生 > >關於Spark報錯不能連線到Server的解決辦法(Failed to connect to master master_hostname:7077)

關於Spark報錯不能連線到Server的解決辦法(Failed to connect to master master_hostname:7077)

問題產生

Spark叢集,即可以基於Mesos或YARN來部署,也可以用自帶的叢集管理器,部署於standalone模式下。筆者在部署standalone模式時,

首先,通過如下命令,啟動了Master。

./sbin/start-master.sh

成功啟動後,可以通過http://master_ip:8080/連線到Master的UI,並在頁面中找到URL為spark://host_name:7077。

然後,通過如下命令,啟動Slave。

./sbin/start-slave.sh spark://host_name:7077

但Slave無法連線Master,查它的Log,可以得到如下錯誤。

17
/02/20 15:31:12 INFO Worker: Retrying connection to master (attempt # 2) 17/02/20 15:31:12 INFO Worker: Connecting to master 10.xx.xx.xx:7077... 17/02/20 15:31:12 WARN Worker: Failed to connect to master 10.xx.xx.xx:7077 org.apache.spark.SparkException: Exception thrown in awaitResult at org.apache.spark.rpc
.RpcTimeout$$anonfun$1.applyOrElse(RpcTimeout.scala:77) at org.apache.spark.rpc.RpcTimeout$$anonfun$1.applyOrElse(RpcTimeout.scala:75) at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) at org.apache.spark.rpc.RpcTimeout$$anonfun$addMessageIfTimeout$1.applyOrElse
(RpcTimeout.scala:59) at org.apache.spark.rpc.RpcTimeout$$anonfun$addMessageIfTimeout$1.applyOrElse(RpcTimeout.scala:59) at scala.PartialFunction$OrElse.apply(PartialFunction.scala:167) at org.apache.spark.rpc.RpcTimeout.awaitResult(RpcTimeout.scala:83) at org.apache.spark.rpc.RpcEnv.setupEndpointRefByURI(RpcEnv.scala:88) at org.apache.spark.rpc.RpcEnv.setupEndpointRef(RpcEnv.scala:96) at org.apache.spark.deploy.worker.Worker$$anonfun$org$apache$spark$deploy$worker$Worker$$tryRegisterAllMasters$1$$anon$1.run(Worker.scala:216) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.io.IOException: Failed to connect to /10.xx.xx.xx:7077 at org.apache.spark.network.client.TransportClientFactory.createClient(TransportClientFactory.java:228) at org.apache.spark.network.client.TransportClientFactory.createClient(TransportClientFactory.java:179) at org.apache.spark.rpc.netty.NettyRpcEnv.createClient(NettyRpcEnv.scala:197) at org.apache.spark.rpc.netty.Outbox$$anon$1.call(Outbox.scala:191) at org.apache.spark.rpc.netty.Outbox$$anon$1.call(Outbox.scala:187) ... 4 more Caused by: java.net.ConnectException: Connection refused: /10.xx.xx.xx:7077 at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:224) at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:289) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111) ... 1 more

這是一個很常見的問題,上網一搜也能發現很多人遇到過。具體怎麼解決這個問題呢,請看下文。

問題解決過程

這到底是網路連線的問題,還是Spark連線的問題呢?下面就是筆者解決這個問題的思路歷程。

關閉防火牆

防火牆有時候會阻止一些連線或埠。再我們不確定哪些服務有用時,最好的辦法就是先將防火牆關閉,確定是防火牆導致的問題,再來調整防火牆的策略。筆者用的是Ubuntu Server,關閉防火牆的命令如下:

ufw disable

然後可以用如下命令來檢查防火牆的狀態:

ufw status verbose

對於這個問題,關了防火牆,發現還是報相同的錯誤資訊。繼續思考其它方案。

修改hostname

筆者Master所在的Linux,hostname是root,太簡單,連線spark://host_name:7077會不會被DNS解析到其它主機。在Master主機修改hostname,需要修改兩個檔案,命令如下。

vim /etc/hostname 
vim /etc/hosts

修改後,啟動Master,再啟動Slave連線spark://new_host_name:7077,依然報錯。猜測是連線不到new_host_name,改為啟動Slave連線spark://master_ip:7077,依然報錯。猜測是連線不到new_host_name,改為啟動Slave連線spark

用nmap確認能連線Master主機埠7077

那麼,是不是Master的7077埠不能連線呢?下載nmap工具(apt install nmap),在Slave主機用如下命令測試:

nmap -p 7077 master_ip

確認7077埠是可以連線的。

python環境

筆者環境中預設是python版本是2.7,而筆者用virtualenv將Spark執行在Python3.5環境中。
這裡無論是用python2.7還是Python3.5的virtualenv,都不能解決問題。

JDK配置

筆者的JAVA_HOME,CLASSPATH,PATH都寫在~/.bashrc,這裡用source命令重新使能這幾個環境變數。依然無法解決問題。

修改Spark配置檔案

在stackoverflow上,筆者還查到了大量修改conf/spark-env.sh的做法,如這裡。這些修改都分別在Master和Slave都做了,還是沒法解決問題。

新增master啟動引數

最後,在stackoverflow上發現了一個很小眾的答案,修改了Master的啟動方法:

./sbin/start-master.sh -h master_ip

成功啟動後,可以通過http://master_ip:8080/連線到Master的UI,並在頁面中找到URL為spark://master_ip:7077。注意這裡的URL已經由spark://host_name:7077變為spark://master_ip:7077。

然後,通過如下命令,成功啟動了Slave!!

./sbin/start-slave.sh spark://master_ip:7077

結論

Best Practice:用-h引數啟動Master,連線到Master的UI,確保URL是spark://master_ip:7077,而非spark://host_name:7077。這樣Slave連線Master的問題不會再出現。