spark技術内幕:master基于zookeeper的high availability(ha)源碼實作 詳細闡述了使用zk實作的master的ha,那麼master是如何快速故障恢複的呢?
處于standby狀态的master在接收到org.apache.spark.deploy.master.zookeeperleaderelectionagent發送的electedleader消息後,就開始通過zk中儲存的application,driver和worker的中繼資料資訊進行故障恢複了,它的狀态也從recoverystate.standby變為recoverystate.recovering了。當然了,如果沒有任何需要恢複的資料,master的狀态就直接變為recoverystate.alive,開始對外服務了。
一方面master通過
恢複application,driver和worker的狀态,一方面通過
在60s後主動向自己發送completerecovery的消息,開始恢複資料完成後的操作。
首先看一下如何通過zookeeperleaderelectionagent提供的接口恢複資料。
擷取了原來的master維護的application,driver和worker的清單後,目前的master通過beginrecovery來恢複它們的狀态。
恢複application的步驟:
置待恢複的application的狀态為unknown,向appclient發送masterchanged的消息
appclient收到後改變其儲存的master的資訊,包括url和master actor的資訊,回複masterchangeacknowledged(appid)
master收到後通過appid後将application的狀态置為waiting
檢查如果所有的worker和application的狀态都不是unknown,那麼恢複結束,調用completerecovery()
恢複worker的步驟:
重新注冊worker(實際上是更新master本地維護的資料結構),置狀态為unknown
向worker發送masterchanged的消息
worker收到消息後,向master回複 消息workerschedulerstateresponse,并通過該消息上報executor和driver的資訊。
master收到消息後,會置該worker的狀态為alive,并且會檢查該worker上報的資訊是否與自己從zk中擷取的資料一緻,包括executor和driver。一緻的executor和driver将被恢複。對于driver,其狀态被置為running。
beginrecovery的源碼實作:
通過下面的流程圖可以更加清晰的了解這個過程:
如何判斷恢複是否結束?
在上面介紹application和worker的恢複時,提到了每次收到他們的回應,都要檢查是否目前所有的worker和application的狀态都不為unknown,如果是,那麼恢複結束,調用completerecovery()。這個機制并不能完全起作用,如果有一個worker恰好也是當機了,那麼該worker的狀态會一直是unknown,那麼會導緻上述政策一直不會起作用。這時候第二個判斷恢複結束的标準就其作用了:逾時機制,選擇是設定了60s得逾時,在60s後,不管是否有worker或者appclient未傳回相應,都會強制标記目前的恢複結束。對于那些狀态仍然是unknown的app和worker,master會丢棄這些資料。具體實作如下:
但是對于一個擁有幾千個節點的叢集來說,60s設定的是否合理?畢竟現在沒有使用standalone模式部署幾千個節點的吧?是以寫死60s看上去也十分合理,畢竟都是邏輯很簡單的調用,如果一些節點60s沒有傳回,那麼下線這部分機器也是合理的。
通過設定spark.worker.timeout,可以自定義逾時時間。