Spark定製班第3課:通過案例對SparkStreaming透徹理解三板斧之三:解密Spark Streaming運行機制和架構進階之Job和容錯


本期內容:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章