本期內容:
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否則會報錯
運行結果:
執行完畢去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!