Spark版本定製第1天:通過案例對SparkStreaming透徹理解之一

本期內容:

1 Spark Streaming另類在線實驗

2 瞬間理解Spark Streaming本質

在流處理時代,SparkStreaming有着強大吸引力,而且發展前景廣闊,加之Spark的生態系統,Streaming可以方便調用其他的諸如SQL,MLlib等強大框架,它必將一統天下。這裏選擇Spark Streaming作爲版本定製的切入點也是大勢所趨。

小技巧:將Batch interval放大,相當於看到了Streaming的慢放版本,可以更清楚它的各個環節,這裏以黑名單過濾程序爲例,進行試驗

案例源碼

package com.dt.spark.sparksteaming
 
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.Seconds
/**
 * 使用Scala開發集羣運行的Spark 在線黑名單過濾程序
 * @author DT大數據夢工廠
 * 新浪微博:http://weibo.com/ilovepains/
 *
 * 背景描述:在廣告點擊計費系統中,我們在線過濾掉黑名單的點擊,進而保護廣告商的利益,只進行有效的廣告點擊計費
 *  或者在防刷評分(或者流量)系統,過濾掉無效的投票或者評分或者流量;
 * 實現技術:使用transform Api直接基於RDD編程,進行join操作
 *
 */
object OnlineBlackListFilter {
    def main(args: Array[String]){
      /**
       * 第1步:創建Spark的配置對象SparkConf,設置Spark程序的運行時的配置信息
       */
      val conf = new SparkConf() //創建SparkConf對象
      conf.setAppName("OnlineBlackListFilter") //設置應用程序的名稱,在程序運行的監控界面可以看到名稱
      conf.setMaster("spark://Master:7077") //此時,程序在Spark集羣
        
      val ssc = new StreamingContext(conf, Seconds(30))//這裏可以將Batch interval調整到更大,例如300秒,以便更好的瞭解Streaming內幕
       
      /**
       * 黑名單數據準備,實際上黑名單一般都是動態的,例如在Redis或者數據庫中,黑名單的生成往往有複雜的業務
       * 邏輯,具體情況算法不同,但是在Spark Streaming進行處理的時候每次都能工訪問完整的信息
       */
      val blackList = Array(("hadoop", true),("mahout", true))
      val blackListRDD = ssc.sparkContext.parallelize(blackList, 8)
       
      val adsClickStream = ssc.socketTextStream("Master", 9999)
       
      /**
       * 此處模擬的廣告點擊的每條數據的格式爲:time、name
       * 此處map操作的結果是name、(time,name)的格式
       */
      val adsClickStreamFormatted = adsClickStream.map { ads => (ads.split(" ")(1), ads) }
      adsClickStreamFormatted.transform(userClickRDD => {
        //通過leftOuterJoin操作既保留了左側用戶廣告點擊內容的RDD的所有內容,又獲得了相應點擊內容是否在黑名單中
        val joinedBlackListRDD = userClickRDD.leftOuterJoin(blackListRDD)
         
        /**
         * 進行filter過濾的時候,其輸入元素是一個Tuple:(name,((time,name), boolean))
         * 其中第一個元素是黑名單的名稱,第二元素的第二個元素是進行leftOuterJoin的時候是否存在在值
         * 如果存在的話,表面當前廣告點擊是黑名單,需要過濾掉,否則的話則是有效點擊內容;
         */
        val validClicked = joinedBlackListRDD.filter(joinedItem => {
          if(joinedItem._2._2.getOrElse(false))
          {
            false
          } else {
            true
          }
        })
         
        validClicked.map(validClick => {validClick._2._1})
      }).print
       
      /**
       * 計算後的有效數據一般都會寫入Kafka中,下游的計費系統會從kafka中pull到有效數據進行計費
       */
      ssc.start()
      ssc.awaitTermination()
      
    }
}
 

運行分析

啓動hdfs和spark集羣並啓動historyServer,將上述代碼打成jar包放入/project/bin/目錄下,爲方便這裏還是命名爲robinspark-1.0-SNAPSHOT.jar。編輯腳本文件start.sh 如下:

$SPARK_HOME/bin/spark-submit \
        --class com.dt.spark.sparkstreaming.OnlineBlackListFilter \
        --master spark://Master:7077 \
        ./robinspark-1.0-SNAPSHOT.jar
        --f

 

運行腳本文件

root@Master:/project/bin# sh -x start.sh

注意:

這裏需要啓動nc -lk 9999否則會報錯

root@Master:/# nc -lk 9999
22222 Spark
3333 flink
4444 mahout
1111 spark
444444 hadoop
5555 kafka
6666 hdfs
8888 java

運行結果:


執行完畢去SparkUI查看job


點擊進入DAG圖


從DAG圖中可以看到這裏並不是應用程序的邏輯,這說明Spark Streaming本身更像是一個應用程序,它在啓動的時候會自動啓動一些作業,執行好幾個job。這時進入details,會發現有一個Receiver在接受數據,而且有一個task運行了7.7min,而打開historyServer會發現整個應用程序也就執行了9.4min。這個7.7min的task就是Receiver在不斷循環的接受數據。從這裏可以看出,Spark Streaming啓動Receiver是通過job啓動的,Receiver接受數據和普通job沒有區別。我們從一臺機器上接受數據,可以在多個機器上執行,最大化的利用資源。在整個過程中雖然產生了很多job,但真正只有一個作業在執行。

Spark Streaming本身是隨着流進來的數據,按照時間爲單位生成job,觸發job在cluster上執行的流式處理引擎。從實質上講,它是加上了時間維度的批處理。每隔一段時間,就會有一批數據流入,通過DStream模版不斷的產生RDD,觸發job並處理。

 

資料來源於:王家林(Spark版本定製班課程)
新浪微博:http://www.weibo.com/ilovepains

Life is short,you need to Spark!

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