在流处理时代,SparkStreaming有着强大吸引力,而且发展前景广阔,加之Spark的生态系统,Streaming可以方便调用其他诸如SQL,MLlib等强大框架,它必将一统天下。这里选择Spark Streaming作为版本定制的切入点也是大势所趋。
将Batch interval放大,相当于看到了Streaming的慢放版本,可以清楚他的各个环节,这里以黑名单过滤程序为列,进行实验。
整个OnlineBlackListFilter应用也就2分钟,而数据接收器receiver运行了1.5分钟,receiver一直不断在接收数据,启动receiver是一个job。receiver在一个work上运行,receiver跟普通的job没有什么区别,为后续的job做准备。复杂程序有多个job,receiver是写复杂程序的黄金切入点。
receiver的PROCESS_LOCAL是内存切入点,直接使用内存中的数据。receiver是1个executor,处理数据是4个executor
spark-submit其实只有一个作业,但是web ui里显示里面有很多job的
object OnlineBlackListFilter {
def main(args: Array[String]) {
//第一步:创建Spark的配置对象SparkConf,设置Spark程序的运行时的配置信息
val conf = new 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})
//计算后的有效数据一般都会写入kafka中,下游的计费系统会从kafka中pull到有效数据进行计费
ssc.start()
ssc.awaitTermination()
}
}