一.SparkStreaming
163.SparkStreaming概述
![](https://i-blog.csdnimg.cn/direct/4355483d7b254ded83ae54ccdcad6ddb.png)
Spark Streaming is an extension of the core Spark API that
enables scalable, high-throughput, fault-tolerant stream
processing of live data streams.
Spark Streaming 是核心 Spark API 的扩展,支持实时数据流的
可扩展、高吞吐量、容错流处理。
Spark Streaming 用于流式数据的处理。 Spark Streaming 支持
的数据输入源很多,例如: Kafka 、 Flume 、 HDFS 、 Kinesis 和 TCP
套接字等等。数据输入后可以用 Spark 的高级函数(如 map 、
reduce 、 join 和 window 等进行运算。而结果也能保存在很多地方,
如 HDFS ,数据库和实时仪表板等。还可以可以在数据流上应用
Spark 的机器学习和图形处理算法。
Spark Streaming 接收实时输入数据流,并将数据分为多个批
次,然后由 Spark 引擎进行处理,以批量生成最终结果流。在内部,
它的工作原理如下:
![](https://i-blog.csdnimg.cn/direct/c716773a089847dfabfe61fd643c271c.png)
164.SparkStreaming_架构
背压机制 ( 了解 ) Spark 1.5 以前版本,用户如果要限制 Receiver 的数据接收速
率,可以通过设置静态配制参数
"spark.streaming.receiver.maxRate" 的值来实现,此举虽然可以通
过限制接收速率,来适配当前的处理能力,防止内存溢出,但也会
引入其它问题。比如: producer 数据生产高于 maxRate ,当前集群
处理能力也高于 maxRate ,这就会造成资源利用率下降等问题。
为了更好的协调数据接收速率与资源处理能力, 1.5 版本开始
Spark Streaming 可以动态控制数据接收速率来适配集群数据处理
能力。背压机制(即 Spark Streaming Backpressure ) : 根据
JobScheduler 反馈作业的执行信息来动态调整 Receiver 数据接收
率。
通过属性 "spark.streaming.backpressure.enabled" 来控制是
否启用 backpressure 机制,默认值 false ,即不启用。
165.SparkStreaming_创建项目
<dependency>
<groupId> org.apache.spark </groupId>
<artifactId> spark-core_2.12 </artifactId>
<version> 3.2.1 </version>
</dependency>
<dependency>
<groupId> org.apache.spark </groupId>
<artifactId> spark
streaming_2.12 </artifactId>
<version> 3.2.1 </version>
</dependency>
166.SparkStreaming_WORDCOUNT
![](https://i-blog.csdnimg.cn/direct/fb088fece3844e7ebd3d150a09b7c038.png)
package com . itbaizhan . streaming
import org . apache . spark . SparkConf
import org . apache . spark . streaming . dstream .
{ DStream , ReceiverInputDStream }
import org . apache . spark . streaming .{ Seconds ,
StreamingContext }
object StreamingWordCount {
def main ( args : Array [ String ]): Unit = {
//1. 初始化 SparkConf 类的对象
val conf : SparkConf = new SparkConf ()
. setMaster ( "local[*]" )
. setAppName ( "StreamingWordCount" )
//2. 创建 StreamingContext 对象
val ssc = new StreamingContext ( conf ,
Seconds ( 5 ))
//3. 通过监控 node1 的 9999 端口创建 DStream 对象
val lines : ReceiverInputDStream [ String ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
7 测试
1
在 node1 上
2
在 IDEA 中运行程序
3
在 node1 上
4
查看 IDEA 控制台
ssc . socketTextStream ( "node1" , 9999 )
//4. 将每一行数据做切分,形成一个个单词
val wordsDS : DStream [ String ] =
lines . flatMap ( _ . split ( " " ))
//5.word=>(word,1)
val wordOne : DStream [( String , Int )] =
wordsDS . map (( _ , 1 ))
//6. 将相同的 key 的 value 做聚合加
val wordCount : DStream [( String , Int )] =
wordOne . reduceByKey ( _ + _ )
//7. 打印输出
wordCount . print ()
//8. 启动
ssc . start ()
//9. 等待执行停止
ssc . awaitTermination ()
}
}
167.SparkStreaming_数据抽象
![](https://i-blog.csdnimg.cn/direct/c3b663db055b4401b82a2bc290e427b8.png)
![](https://i-blog.csdnimg.cn/direct/8b57410c60de4dd6a68852477163b165.png)
168.SparkStreaming_RDD队列创建DSTREAM
![](https://i-blog.csdnimg.cn/direct/ce6cd44164a640db88b30062e083fd4e.png)
![](https://i-blog.csdnimg.cn/direct/2d13bbc17fcb43e58738306f33261e70.png)
![](https://i-blog.csdnimg.cn/direct/d9f55cd20649478db8d7c3be202eb5fa.png)
![](https://i-blog.csdnimg.cn/direct/91b3a7a55b1241d99299ff6a7e076eb4.png)
169.SparkStreaming_自定义数据源一
需求:自定义数据源,实现监控指定的端口号,获取该端口号
内容。
需要继承 Receiver ,并实现 onStart 、 onStop 方法来自定义数据源采集。
package com . itbaizhan . streaming
import org . apache . spark . storage . StorageLevel
import
org . apache . spark . streaming . receiver . Receiver
import java . io .{ BufferedReader ,
InputStreamReader }
import java . net . Socket
import java . nio . charset . StandardCharsets
1
2
3
4
5
6
7
8
9
13 class ReceiverCustomer ( host : String , port :
Int ) extends Receiver [ String ]
( StorageLevel . MEMORY_ONLY ) {
// 最初启动的时候,调用该方法
// 作用:读数据并将数据发送给 Spark
override def onStart (): Unit = {
new Thread ( "Socket Receiver" ) {
override def run () {
receive ()
}
}. start ()
}
override def onStop (): Unit = {}
// 读数据并将数据发送给 Spark
def receive (): Unit = {
// 创建一个 Socket
var socket : Socket = new Socket ( host ,
port )
// 定义一个变量,用来接收端口传过来的数据
var input : String = null
// 创建一个 BufferedReader 用于读取端口传来的数
据
val reader = new BufferedReader ( new
InputStreamReader ( socket . getInputStream ,
StandardCharsets . UTF_8 ))
// 读取数据
input = reader . readLine ()
// 当 receiver 没有关闭并且输入数据不为空,则循环
发送数据给 Spark
while ( ! isStopped () && input != null ) {
store ( input )
input = reader . readLine ()
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
14 使用自定义的数据源采集数据
}
// 跳出循环则关闭资源
reader . close ()
socket . close ()
// 重启任务
restart ( "restart" )
}
}
170.SparkStreaming_自定义数据源二
package com . itbaizhan . streaming
import org . apache . spark . SparkConf
import org . apache . spark . streaming .{ Seconds ,
StreamingContext }
object CustomerSource {
def main ( args : Array [ String ]): Unit = {
//1. 初始化 Spark 配置信息
val sparkConf = new SparkConf ()
. setMaster ( "local[*]" )
. setAppName ( "CustomerSource" )
//2. 初始化
val ssc = new
StreamingContext ( sparkConf , Seconds ( 5 ))
//3. 创建自定义 receiver 的 Streaming
val lines = ssc . receiverStream ( new
ReceiverCustomer ( "node1" , 9999 ))
lines . print ()
//4. 启动
ssc . start ()
ssc . awaitTermination ()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
15 测试
1
在 node1 上
2
在 IDEA 中运行程序
3
在 node1 上
4
查看 IDEA 控制台
实时效果反馈
1. 关于 SparkStreaming 接收器自定义数据源的描述,错误的
是:
A
需要继承 Receiver ,并实现 onStart 、 onStop 方法来自定义
数据源采集。
B
Xxx extends Receiver[String](StorageLevel.MEMORY_ONLY)
接收到数据仅保存在
内存中。
C
onStart()
最初启动的时候,调用该方法;作用是读数据并将数
据发给 Spark 。
D
onStop()
不能空实现。
答案:
1=>D 可以空实现
SparkStreaming_DStream 无状态转换
}
}
20
21
[root@node1 ~] # nc -lk 9999
1
[root@node1 ~] # nc -lk 9999
aa
bb
cc
171.SparkStreaming_DSTREAM无状态转换
![](https://i-blog.csdnimg.cn/direct/8742df5e1ca24be8a190552d8593a110.png)
172.SparkStreaming_DSTREAM无状态转换transform
![](https://i-blog.csdnimg.cn/direct/e5431005e636451ea06405dc3a129711.png)
![](https://i-blog.csdnimg.cn/direct/58825b10d0734961b99e5fc48606941e.png)
173.SparkStreaming_DSTREAM有状态转换
![](https://i-blog.csdnimg.cn/direct/f3f619da916f4b61b38da5db84b2cd0a.png)
![](https://i-blog.csdnimg.cn/direct/dd0f65f7b67d46059e7bd2bc92f1b65a.png)
174.SparkStreaming_窗口操作reducebykeyandwidow概述
//reduceFunc-- 结合和交换 reduce 函数
//windowDuration-- 窗口长度;必须是此数据流批处理间
隔的倍数
//slideDuration-- 窗口的滑动间隔 , 即新数据流生成 RDD
的间隔
def reduceByKeyAndWindow (
reduceFunc : ( V , V ) => V ,
windowDuration : Duration ,
slideDuration : Duration
): DStream [( K , V )] = ssc . withScope {
//partitioner-- 用于控制新数据流中每个 RDD 分区的
分区器
reduceByKeyAndWindow ( reduceFunc ,
windowDuration , slideDuration ,
defaultPartitioner ())
}
175.SparkStreaming_窗口操作reducebykeyandwidow实战
![](https://i-blog.csdnimg.cn/direct/837069bb82aa4a899d387d20d4bb8934.png)
![](https://i-blog.csdnimg.cn/direct/2be9b8a6c59d430a895ea918df1ebc84.png)
![](https://i-blog.csdnimg.cn/direct/f61732b8919c477fa41b1a33d22bb64d.png)
176.SparkStreaming_窗口操作reducebykeyandwidow优化
![](https://i-blog.csdnimg.cn/direct/b30fe304213a4f249e088b4361ec7bf3.png)
![](https://i-blog.csdnimg.cn/direct/789105756a27410f968a85379ba54de4.png)
177.SparkStreaming_窗口操作WINDOW
![](https://i-blog.csdnimg.cn/direct/7900b6b2069c47e6a3941c3fdde8e5d0.png)
![](https://i-blog.csdnimg.cn/direct/b1b7332c6e33485fb789c44122d6ca7c.png)
![](https://i-blog.csdnimg.cn/direct/f7a91d6128a944c69c453cf031f03af4.png)