1 解密Spark Streaming Job 架構和運行機制
2 解密Spark Streaming Job 容錯架構和運行機制
1 解密Spark Streaming Job 架構和運行機制
理解Spark Streaming的Job的整個架構和運行機制對於精通Spark Streaming是至關重要的。
我們運行以下的程序,通過這個程序的運行過程進一步加深理解Spark Streaming流處理的Job的執行的過程,代碼如下:
object OnlineForeachRDD2DB {
def main(args: Array[String]){
/**
* 第1步:創建Spark的配置對象SparkConf,設置Spark程序的運行時的配置信息,
* 例如說通過setMaster來設置程序要鏈接的Spark集羣的Master的URL,如果設置
* 爲local,則代表Spark程序在本地運行,特別適合於機器配置條件非常差(例如
* 只有1G的內存)的初學者
*/
val conf = new SparkConf() //創建SparkConf對象
conf.setAppName("OnlineForeachRDD") //設置應用程序的名稱,在程序運行的監控界面可以看到名稱
conf.setMaster("spark://Master:7077") //此時,程序在Spark集羣
conf.setMaster("local[6]")
//設置batchDuration時間間隔來控制Job生成的頻率並且創建Spark Streaming執行的入口
val ssc = new StreamingContext(conf, Seconds(5))
val lines = ssc.socketTextStream("Master", 9999)
val words = lines.flatMap(_.split(" "))
val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _)
wordCounts.foreachRDD{ rdd =>
rdd.foreachPartition{ partitionOfRecords => {
// ConnectionPool is a static, lazily initialized pool of connections
val connection = ConnectionPool.getConnection()
partitionOfRecords.foreach(record => {
val sql = "insert into streaming_itemcount(item,count) values('" + record._1 + "'," + record._2 + ")"
val stmt = connection.createStatement();
stmt.executeUpdate(sql);
})
ConnectionPool.returnConnection(connection) // return to the pool for future reuse
}}
}
/**
* 在StreamingContext調用start方法的內部其實是會啓動JobScheduler的Start方法,進行消息循環,
* 在JobScheduler的start內部會構造JobGenerator和ReceiverTacker,並且調用JobGenerator和
* ReceiverTacker的start方法:
* 1,JobGenerator啓動後會不斷的根據batchDuration生成一個個的Job
* 2,ReceiverTracker啓動後首先在Spark Cluster中啓動Receiver(其實是在Executor中先啓動
* ReceiverSupervisor),在Receiver收到數據後會通過ReceiverSupervisor存儲到Executor並且把
* 數據的Metadata信息發送給Driver中的ReceiverTracker,在ReceiverTracker內部會通過
* ReceivedBlockTracker來管理接受到的元數據信息每個BatchInterval會產生一個具體的Job,
* 其實這裏的Job不是Spark Core中所指的Job,它只是基於DStreamGraph而生成的RDD的DAG
* 而已,從Java角度講,相當於Runnable接口實例,此時要想運行Job需要提交給JobScheduler,
* 在JobScheduler中通過線程池的方式找到一個單獨的線程來提交Job到集羣運行(其實是在線程中
* 基於RDD的Action觸發真正的作業的運行),
* 爲什麼使用線程池呢?
* 1,作業不斷生成,所以爲了提升效率,我們需要線程池;這和在Executor中通過線程池執行Task
* 有異曲同工之妙;
* 2,有可能設置了Job的FAIR公平調度的方式,這個時候也需要多線程的支持。
*/
ssc.start()
ssc.awaitTermination()
}
}
2 解密Spark Streaming Job容錯架構和運行機制
Spark容錯分爲Driver級別的容錯和Executor級別的容錯。
- 在Driver級別的容錯具體爲DAG生成的模板,即DStreamGraph,RecevierTracker中存儲的元數據信息和JobScheduler中存儲的Job進行的進度情況等信息,只要通過checkpoint就可以了,每個Job生成之前進行checkpoint,在Job生成之後再進行checkpoint,如果出錯的話就從checkpoint中恢復。
- 在Executor級別的容錯具體爲接收數據的安全性和任務執行的安全性。在接收數據安全性方面,一種方式是Spark Streaming接收到數據默認爲MEMORY_AND_DISK_2的方式,在兩臺機器的內存中,如果一臺機器上的Executor掛了,立即切換到另一臺機器上的Executor,這種方式一般情況下非常可靠且沒有切換時間。另外一種方式是WAL(Write Ahead Log),在數據到來時先通過WAL機制將數據進行日誌記錄,如果有問題則從日誌記錄中恢復,然後再把數據存到Executor中,再進行其他副本的複製。WAL這種方式對性能有影響,在生產環境中不常用,一般使用Kafka存儲,Spark Streaming接收到數據丟失時可以從Kafka中回放。在任務執行的安全性方面,靠RDD的容錯。
Spark Streaming的容錯機制是基於RDD的容錯機制。
主要表現爲:
1 checkpoint
2 基於血統(lineage)的高度容錯機制
3 出錯了之後會從出錯的位置從新計算,而不會導致重複計算
備註:
資料來源於:DT_大數據夢工廠(Spark發行版本定製)
更多私密內容,請關注微信公衆號:DT_Spark
如果您對大數據Spark感興趣,可以免費聽由王家林老師每天晚上20:00開設的Spark永久免費公開課,地址YY房間號:68917580