Spark Streaming 是核心Spark API的扩展,可实现实时数据流的可伸缩,高吞吐量,容错流处理。可以从许多数据源(例如Kafka,Flume,Kinesis或TCP sockets)中提取数据,并且可以使用复杂的算法处理数据,这些算法用高级函数表示,如map、reduce、join和window。最后,可以将处理后的数据推送到文件系统,数据库和实时仪表板。实际上,可以在数据流上应用Spark的机器学习和图形处理算法。

在内部,它的工作方式如下。 Spark Streaming接收实时输入数据流,并将数据分成批次,然后由Spark引擎进行处理,以生成批次的最终结果流。

Spark Streaming提供了一种高级抽象,称为离散流或DStream,它表示连续的数据流。DStreams可以从Kafka、Flume和Kinesis等源的输入数据流创建,也可以通过在其他DStreams上应用高级操作创建。在内部,DStream表示为RDDs序列。

1. 了解Spark

Apache Spark 是一个用于大规模数据处理的统一分析引擎

    

特性:

将工作负载运行速度提高100倍

Apache Spark使用最新的DAG调度程序,查询优化器和物理执行引擎,为批处理数据和流数据提供了高性能。

易用

可以使用Java,Scala,Python,R和SQL快速编写应用程序。

通用

结合SQL、流和复杂的分析

Spark为包括SQL和DataFrames,用于机器学习的MLlib,GraphX和Spark Streaming在内的一堆库提供支持。您可以在同一应用程序中无缝组合这些库。

到处运行

Spark可在Hadoop,Apache Mesos,Kubernetes,独立或云中运行。它可以访问各种数据源。

可以在EC2,Hadoop YARN,Mesos或Kubernetes上使用其独立集群模式运行Spark。访问HDFS,Alluxio,Apache Cassandra,Apache HBase,Apache Hive和数百种其他数据源中的数据。

2. 入门案例

统计单词出现的次数,这个例子在Hadoop中用MapReduce也写过。

JavaStreamingContext是java版的StreamingContext。它是Spark Streaming功能的主要入口点。它提供了从输入源创建JavaDStream和JavaPairDStream的方法。可以使用context.sparkContext访问内部的org.apache.spark.api.java.JavaSparkContext。在创建和转换DStream之后,可以分别使用context.start()和context.stop()启动和停止流计算。

 1 public static void main(String[] args) throws InterruptedException {
2 // Create a local StreamingContext with two working thread and batch interval of 1 second
3 SparkConf conf = new SparkConf().setMaster("local[2]").setAppName("NetworkWordCount");
4 JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds());
5
6 // Create a DStream that will connect to hostname:port, like localhost:9999
7 JavaReceiverInputDStream<String> lines = jssc.socketTextStream("localhost", );
8
9 // Split each line into words
10 JavaDStream<String> words = lines.flatMap(x -> Arrays.asList(x.split(" ")).iterator());
11
12 // Count each word in each batch
13 JavaPairDStream<String, Integer> pairs = words.mapToPair(s -> new Tuple2<>(s, ));
14 JavaPairDStream<String, Integer> wordCounts = pairs.reduceByKey((i1, i2) -> i1 + i2);
15
16 // Print the first ten elements of each RDD generated in this DStream to the console
17 wordCounts.print();
18
19 // Start the computation
20 jssc.start();
21 // Wait for the computation to terminate
22 jssc.awaitTermination();
23 }

3. 基本概念

3.1. Maven依赖

1 <groupId>org.apache.spark</groupId>
2 <artifactId>spark-streaming_2.12</artifactId>
3 <version>2.4.5</version>
4 <scope>provided</scope>
5 </dependency>

为了从其它数据源获取数据,需要添加相应的依赖项spark-streaming-xyz_2.12。例如:

1 <dependency>
2 <groupId>org.apache.spark</groupId>
3 <artifactId>spark-streaming-kafka-0-10_2.12</artifactId>
4 <version>2.4.5</version>
5 </dependency>

3.2. 初始化StreamingContext

为了初始化一个Spark Streaming程序,必须创建一个StreamingContext对象,该对象是所有Spark Streaming功能的主要入口点。

我们可以从SparkConf对象中创建一个JavaStreamingContext对象

1 import org.apache.spark.SparkConf;
2 import org.apache.spark.streaming.Duration;
3 import org.apache.spark.streaming.api.java.JavaStreamingContext;
4
5 SparkConf conf = new SparkConf().setAppName(appName).setMaster(master);
6 JavaStreamingContext ssc = new JavaStreamingContext(conf, new Duration()); 

appName 参数是显示在集群UI上的你的应用的名字

master 参数是一个Spark、 Mesos 或 YARN 集群URL,或者也可以是一个特定的字符串“local[*]”表示以本地模式运行。实际上,当在集群上运行时,肯定不希望对在程序中对master进行硬编码,而希望通过spark-submit启动应用程序并在其中接收它。然而,对于本地测试,你可以传“local[*]”来运行Spark Streaming。

还可以从一个已存在的JavaSparkContext中创建一个JavaStreamingContext对象

1 import org.apache.spark.streaming.api.java.*;
2
3 JavaSparkContext sc = ... //existing JavaSparkContext
4 JavaStreamingContext ssc = new JavaStreamingContext(sc, Durations.seconds());

在定义完context之后,必须做以下事情:

  1. 通过创建input DStreams来定义input sources
  2. 通过对DStreams应用transformation(转换)和output(输出)操作来定义流计算
  3. 用streamingContext.start()来开始接收数据并处理它
  4. 用streamingContext.awaitTermination()等待处理停止(手动停止或由于任何错误)
  5. 用streamingContext.stop()可以手动停止

需要记住的点:

  • 一旦启动上下文,就无法设置新的流计算或将其添加到该流计算中
  • 上下文一旦停止,就无法重新启动
  • 一个JVM中只能同时激活一个StreamingContext
  • StreamingContext中的stop()也会停止SparkContext。但如果要仅停止StreamingContext的话,设置stop(false)
  • 只要在创建下一个StreamingContext之前停止了上一个StreamingContext(不停止SparkContext),就可以将SparkContext重用于创建多个StreamingContext

3.3. DStreams(离散流)

Discretized Stream 或 DStream 是Spark Streaming提供的基本抽象。它表示一个连续的数据流,可以是从源接收的输入数据流,也可以是通过转换输入流生成的已处理数据流。在内部,DStream由一系列连续的RDD表示,这是Spark对不变的分布式数据集的抽象。DStream中的每个RDD都包含来自特定间隔的数据,如下图所示。

在DStream上执行的任何操作都转换为对基础RDD的操作。例如,最简单的将一行句子转换为单词的例子中,flatMap操作应用于行DStream中的每个RDD,以生成单词DStream的RDD。如下图所示:

3.4. Input DStreams 和 Receivers

Input DStream是表示从源接收的输入数据流。在上图中,lines是输入DStream,因为它表示从netcat服务器接收的数据流。每一个输入DStream都关联着一个Receiver对象,该对象从源接收数据并将其存储在Spark的内存中以进行处理。

Spark Streaming提供了两类内置的streaming源:

  • Basic sources :直接在StreamingContext API中可用的源。例如,文件系统和socket连接
  • Advanced sources :像Kafka,Flume,Kinesis等这样的源,可通过额外的程序类获得

如果要在流应用程序中并行接收多个数据流,则可以创建多个输入DStream。这将创建多个Receiver(接收器),这些接收器将同时接收多个数据流。重要的是要记住,必须为Spark Streaming应用程序分配足够的内核(或线程,如果在本地运行),以处理接收到的数据以及运行接收器。

需要记住的点:

  • 在本地运行Spark Streaming程序时,请勿使用“ local”或“ local [1]”作为master URL。这两种方式均意味着仅一个线程将用于本地运行任务。如果使用的是基于接收器的输入DStream(例如套接字,Kafka,Flume等),则将使用单个线程来运行接收器,而不会留下任何线程来处理接收到的数据。 因此,在本地运行时,请始终使用“ local [n]”作为主URL,其中n>要运行的接收器数
  • 为了将逻辑扩展到在集群上运行,分配给Spark Streaming应用程序的内核数必须大于接收器数。 否则,系统将接收数据,但无法处理它。

Basic Sources

为了从文件中读取数据,可以通过StreamingContext.fileStream[KeyClass, ValueClass, InputFormatClass]来创建一个DStream

例如:streamingContext.textFileStream(dataDirectory);

Spark Streaming将监视目录dataDirectory并处理在该目录中创建的所有文件

  • 可以监视一个简单的目录,例如:"hdfs://namenode:8040/logs/2017/*"。在这里,DStream将由目录中与模式匹配的所有文件组成。也就是说:它是目录的模式,而不是目录中的文件。
  • 所有文件必须使用相同的数据格式
  • 根据文件的修改时间而不是创建时间,将其视为时间段的一部分
  • 一旦已经被处理后,在当前窗口中对文件的更改不会导致重新读取该文件。即:更新被忽略。

3.5. Transformations on DStreams

对DStreams做转换,与RDD相似,转换允许修改输入DStream中的数据。DStream支持普通Spark RDD上可用的许多转换。一些常见的方法如下:

map(func) 通过将源DStream的每个元素传递给函数func来处理并返回新的DStream
flatMap(func) 与map类似,但是每个输入项可以映射到0个或多个输出项
filter(func) 过滤
repartition(numPartitions)  通过创建更多或更少的分区来更改此DStream中的并行度
union(otherStream)  将源DStream和另一个DStream中的元素合并在一起,返回一个新的DStream。相当于SQL中的union 
count() 返回元素的个数
reduce(func)  通过使用函数func(接受两个参数并返回一个)来聚合源DStream的每个RDD中的元素,从而返回一个单元素RDD的新DStream。 
countByValue() 

在类型为K的元素的DStream上调用时,返回一个新的(K,Long)形式的DStream,其中每个键的值是其在源DStream的每个RDD中的频率。

reduceByKey(func, [numTasks])  在一个(K,V)形式的DStream上调用时,返回一个新的(K,V)DStream,其中使用给定的reduce函数汇总每个键的值
join(otherStream, [numTasks])  在(K,V)和(K,W)两个DStream上调用时,返回一个新的(K,(V,W))DStream 
cogroup(otherStream, [numTasks])  在(K,V)和(K,W)DStream上调用时,返回一个新的(K,Seq [V],Seq [W])元组的DStream 
transform(func)  通过对源DStream的每个RDD应用RDD-to-RDD函数来返回新的DStream。这可用于在DStream上执行任意RDD操作。
updateStateByKey(func)  返回一个新的“state” DStream 

其实,这次操作跟Java Stream很像

Window Operations(窗口操作)

Spark Streaming还提供了窗口计算,可以在数据的滑动窗口上应用转换。下图说明了此滑动窗口:

如图所示,每当窗口在源DStream上滑动时,就会对落入窗口内的源RDD进行操作,以生成窗口DStream的RDD。

任何窗口函数所必须的两个参数:

  • 窗口的长度
  • 滑到的频率(或者说时间间隔)

举个例子,我们来扩展前面的示例,假设我们想要每10秒在数据的最后30秒生成一次单词次数统计。为此,必须在数据的最后30秒内对(word,1)对的DStream对应用reduceByKey操作。

 1 import org.apache.spark.streaming.Durations;
2 import org.apache.spark.streaming.api.java.JavaDStream;
3 import org.apache.spark.streaming.api.java.JavaPairDStream;
4 import scala.Tuple2;
5
6
7 JavaDStream<String> words = lines.flatMap(x -> Arrays.asList(x.split(" ")).iterator());
8 JavaPairDStream<String, Integer> pairs = words.mapToPair(s -> new Tuple2<>(s, ));
9
10 // Reduce last 30 seconds of data, every 10 seconds
11 JavaPairDStream<String, Integer> windowedWordCounts = pairs.reduceByKeyAndWindow((i1, i2) -> i1 + i2, Durations.seconds(), Durations.seconds());

一些常见的窗口操作如下。所有这些操作均采用上述两个参数:windowLength和slideInterval

window(windowLength, slideInterval) 返回基于源DStream的窗口批处理计算的新DStream
countByWindow(windowLength, slideInterval) 返回流中元素的滑动窗口数
reduceByWindow(func, windowLength, slideInterval) 对窗口内的数据进行聚合操作
reduceByKeyAndWindow(func, windowLength, slideInterval, [numTasks]) 在(K,V)DStream上调用时,返回新的(K,V)DStream,其中使用给定的reduce函数func在滑动窗口中的批处理上汇总每个键的值
reduceByKeyAndWindow(func, invFunc, windowLength, slideInterval, [numTasks])  
countByValueAndWindow(windowLength, slideInterval, [numTasks])  

3.6. Output Operations on DStreams

输出操作允许将DStream的数据输出到外部系统,例如数据库或文件系统。

流式应用程序必须24/7全天候运行,因此必须能够抵抗与应用程序逻辑无关的故障(例如,系统故障,JVM崩溃等)。为此,Spark Streaming需要将足够的信息检查点指向容错存储系统,以便可以从故障中恢复。检查点有两种类型的数据。

  • 元数据检查点-将定义流计算的信息保存到HDFS等容错存储中。这用于从运行流应用程序的驱动程序的节点的故障中恢复。
  • 数据检查点-将生成的RDD保存到可靠的存储中

完整代码:

 1 package com.example.demo;
2
3 import org.apache.spark.SparkConf;
4 import org.apache.spark.streaming.Durations;
5 import org.apache.spark.streaming.api.java.JavaDStream;
6 import org.apache.spark.streaming.api.java.JavaPairDStream;
7 import org.apache.spark.streaming.api.java.JavaStreamingContext;
8 import scala.Tuple2;
9
10 import java.util.Arrays;
11 import java.util.regex.Pattern;
12
13 /**
14 * @author ChengJianSheng
15 */
16 public class JavaWordCount {
17
18 private static final Pattern SPACE = Pattern.compile(" ");
19
20 public static void main(String[] args) {
21 if (args.length < ) {
22 System.err.println("Usage: JavaWordCount <file>");
23 System.exit();
24 }
25
26 SparkConf conf = new SparkConf().setMaster("local[*]").setAppName("JavaWordCount");
27 JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds());
28
29 JavaDStream<String> lines = jssc.textFileStream(args[]);
30 JavaDStream<String> words = lines.flatMap(line -> Arrays.asList(SPACE.split(line)).iterator());
31 JavaPairDStream<String, Integer> ones = words.mapToPair(word -> new Tuple2<>(word, ));
32 JavaPairDStream<String, Integer> counts = ones.reduceByKey((i1, i2) -> i1 + i2);
33 counts.print();
34
35 /*
36 JavaStreamingContext jsc = new JavaStreamingContext(conf, Durations.seconds(1));
37 JavaDStream<String> textFileStream = jsc.textFileStream("/data");
38 textFileStream.flatMap(line->Arrays.asList(line.split(" ")).iterator())
39 .mapToPair(word->new Tuple2<>(word, 1))
40 .reduceByKey((a,b)->a+b)
41 .print();
42 jsc.start();
43 */
44 }
45 }

4. Docs

https://spark.apache.org/

https://spark.apache.org/docs/latest/streaming-programming-guide.html

Spark Streaming 编程入门指南的更多相关文章

  1. Apache Spark 2.2.0 中文文档 - Spark Streaming 编程指南 | ApacheCN

    Spark Streaming 编程指南 概述 一个入门示例 基础概念 依赖 初始化 StreamingContext Discretized Streams (DStreams)(离散化流) Inp ...

  2. Apache Spark 2.2.0 中文文档 - Spark Streaming 编程指南

    Spark Streaming 编程指南 概述 一个入门示例 基础概念 依赖 初始化 StreamingContext Discretized Streams (DStreams)(离散化流) Inp ...

  3. 学习笔记:spark Streaming的入门

    spark Streaming的入门 1.概述 spark streaming 是spark core api的一个扩展,可实现实时数据的可扩展,高吞吐量,容错流处理. 从上图可以看出,数据可以有很多 ...

  4. Spark Streaming编程示例

    近期也有开始研究使用spark streaming来实现流式处理.本文以流式计算word count为例,简单描述如何进行spark streaming编程. 1. 依赖的jar包 参考<分别用 ...

  5. 《转载》编程入门指南 v1.4

    编程入门指南 v1.4 Badger · 8 个月前 作者:@萧井陌, @Badger 自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 CoCode ...

  6. Spark Streaming编程指南

    Overview A Quick Example Basic Concepts Linking Initializing StreamingContext Discretized Streams (D ...

  7. Spark Streaming 调优指南

    SparkStreaming是架构在SparkCore上的一个"应用",SparkStreaming主要由DStreamGraph.Job的生成.数据的接收和导入以及容错四大模块组 ...

  8. Spark Streaming 快速入门

    一.简介 1.便于使用 Spark Streaming将Apache Spark的 语言集成API 引入流处理,使您可以像编写批处理作业一样编写流式作业.它支持Java,Scala和Python. 2 ...

  9. Spark官方3 ---------Spark Streaming编程指南(1.5.0)

    Design Patterns for using foreachRDD dstream.foreachRDD是一个强大的原语,允许将数据发送到外部系统.然而,了解如何正确有效地使用该原语很重要.避免 ...

随机推荐

  1. 编写程序实现根据考试成绩将成绩分为A,B,C,D四档。

    score = float(input("请输入你的成绩:"))if 90 <= score <= 100: print("你的成绩为A档")eli ...

  2. Java基础面试系列(一)

    Java基础面试总结(一) 1. 面向对象和面向过程的区别 面向过程 面向对象 性能 高于面向对象 类加载的时候需要实例化,比较消耗资源 三易(易维护,易复用,易扩展) 不如面向对象 具有封装,继承, ...

  3. 学习ConcurrentHashMap1.7分段锁原理

    1. 概述 接上一篇 学习 ConcurrentHashMap1.8 并发写机制, 本文主要学习 Segment分段锁 的实现原理. 虽然 JDK1.7 在生产环境已逐渐被 JDK1.8 替代,然而一 ...

  4. 数据科学中的常见的6种概率分布(Python实现)

    作者:Pier Paolo Ippolito@南安普敦大学 编译:机器学习算法与Python实战(微信公众号:tjxj666) 原文:https://towardsdatascience.com/pr ...

  5. 深入理解“骑士”漏洞 VoltJockey

    先理解一下题目:VoltJockey: Breaching TrustZone by Software-Controlled Voltage Manipulation over Multi-core ...

  6. JVM的组成

    JVM一共有五大区域,程序计数器.虚拟机栈.本地方法栈.Java堆.方法区. 程序计数器 程序技术器是一块很小的内存空间,由于Java是支持多线程的.当线程数大于CPU数量时,CPU会按照时间片轮寻执 ...

  7. Natas18 Writeup(Session登录,暴力破解)

    Natas18: 一个登录界面,查看源码,发现没有连接数据库,使用Session登录,且$maxid设定了不大的上限,选择采取爆破. 源码解析: <html> <head> & ...

  8. sqlmap详解

    sqlmap是一个自动化的sql注入工具,其主要功能是扫描.发现并利用给定URL的SQL注入漏洞,内置了很多绕过插件,支持的数据库有MySQL, Oracle,PostgreSQL, Microsof ...

  9. Head First设计模式——桥接模式

    桥接模式 桥接模式:不只改变你的实现,也改变你的抽象. 如果有一个电视厂家,遥控器需要升级,电视也需要修改.这种变化部分的封装就适合使用桥接模式,桥接模式通过将实现和抽象放在两个不同的类层次中而使它们 ...

  10. HBU-数据库第五周作业

    第五周数据库作业 注意 MySQL的数据库名.表名.列名.别名大小写规则是这样的: 1.数据库名与表名是严格区分大小写的: 2.表的别名是严格区分大小写的: 3.列名与列的别名在所有的情况下均是忽略大 ...