文章目錄
1、概述
官網:http://spark.apache.org/docs/latest/streaming-programming-guide.html
Spark流是核心Spark API的擴展,支持對實時數據流進行可伸縮的、高吞吐量的、容錯的流處理。數據可以從Kafka、Flume、Kinesis或TCP套接字等多種來源獲取,並且可以使用複雜的算法處理數據,這些算法由map、reduce、join和window等高級函數表示。最後,處理後的數據可以推送到文件系統、數據庫和活動儀表板。
在內部,它的工作原理如下。Spark streams接收實時輸入的數據流,並將數據分成批次,然後由Spark引擎對這些數據進行處理,以批量生成最終的結果流。
Spark流提供了一個高級抽象,稱爲discretized stream或DStream,它表示連續的數據流。DStreams可以從Kafka、Flume和Kinesis等源的輸入數據流創建,也可以通過對其他DStreams應用高級操作創建。在內部,DStream表示爲RDDs序列。
所以SparkStreaming嚴格意義上來講並不是實時的,是由很多個小批次組成。
2、Basic Concepts
2.1 Maven 添加依賴
如果是基於Maven的Project,pom.xml要添加spark-streaming依賴包,注意scala版本,我的是scala-2.11.8
<spark.version>2.4.0</spark.version>
...
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
2.2 StreamingContext
StreamingContext是SparkStreaming程序的入口,回顧下前面講的:
RDD入口 => SparkContext
DataFrame/DataSet入口 => SparkSession
DStream入口 => StreamingContextRDD入口 => SparkContext
DataFrame/DataSet入口 => SparkSession
DStream入口 => StreamingContext
import org.apache.spark._
import org.apache.spark.streaming._
val conf = new SparkConf().setAppName(appName).setMaster(master)
val ssc = new StreamingContext(conf, Seconds(1)) //conf不講,Seconds表示多少秒執行一次程序
//TODO...要執行的代碼
ssc.start()
ssc.awaitTermination()
2.3 Discretized Streams (DStreams)
Discretized Stream or DStream是Spark流提供的基本抽象。它表示連續的數據流,無論是從源接收到的輸入數據流,還是通過轉換輸入流生成的經過處理的數據流。在內部,DStream由一系列連續的RDDs表示,RDDs是Spark對不可變的分佈式數據集的抽象。DStream中的每個RDD都包含來自特定時間間隔的數據,如下圖所示。
應用於DStream上的任何操作都轉換爲底層RDDs上的操作。
這些底層的RDD轉換由Spark引擎計算。DStream操作隱藏了這些細節中的大部分,併爲開發人員提供了更高級的API,以方便開發人員使用。
2.4 Input DStreams、 Receiver
Input DStreams是表示從流源接收的輸入數據流的數據流。在官網案例中(該案例往下看),lines是一個Input DStreams,因爲它表示從netcat服務器接收到的數據流。每個Input DStreams都與Receiver對象相關聯,後者接收來自源的數據並將其存儲在Spark內存中進行處理。
注意,如果希望在流應用程序中並行接收多個數據流,可以創建多個input DStreams 。這將創建多個receivers,同時接收多個數據流。但是請注意,Spark worker或者executor端是一個長時間運行的任務,因此它佔用分配給Spark流應用程序的一個Core。因此,重要的是要記住,Spark流應用程序需要分配足夠的內核來處理接收到的數據,並運行receiver。
這段話是說如果你是Local模式的,那麼至少要設置成 local[2]
,因爲executor要佔用1core,receiver接受數據源也要佔用1core。所以像local
,local[1]
是不行的。
2.5 Transformations on DStreams
和SparkCore的算子使用是一樣的,這裏不講解。
參考博客:https://blog.csdn.net/greenplum_xiaofan/article/details/97975195
2.6 Output Operations on DStreams
重點是foreachRDD
3、運行過程
4、官網案例WordCount
先開啓natcat
[hadoop@vm01 bin]$ nc -lk 8888
再開啓SparkStreaming應用程序,從natcat接受數據,每隔10秒一個批次計算WordCount
package com.ruozedata.spark
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
object SocketWCApp {
def main(args: Array[String]): Unit = {
val sparkConf=new SparkConf().setMaster("local[2]").setAppName("SocketWCApp")
val ssc=new StreamingContext(sparkConf,Seconds(10))
//socketTextStream底層源碼裏面就有 Receiver接收器
val lines=ssc.socketTextStream("vm01",8888)
val result=lines.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
result.print()
ssc.start()
ssc.awaitTermination()
}
}
在什麼都沒數據接收過來的情況下,每隔10秒會運行一次
要停止程序,點擊左邊紅色正方形
然後輸入一些數據
[hadoop@vm01 bin]$ nc -lk 8888
hello hadoop
hello spark