SparkStreaming编程指南学习

SparkStreaming编程指南


文章目录

  • SparkStreaming编程指南学习
  • 1:SparkStreaming编程指南
  • 1:概述
  • 2:基本概念
  • 2.1:DStream,DataSet以及DataFrame
  • 2.2:rdd算子介绍
  • 2.3:checkpoint检查点
  • 1:checkpoint存储的数据
  • 2:checkpoint配置
  • 3:使用
  • 4:checkpoint和广播变量
  • 3:sparkStreaming开发
  • 3.1:maven依赖引入
  • 3.2初始化StreamingContext
  • 3.3:DStream 常见操作
  • 1:窗口函数操作
  • 2:join操作
  • 3:Dstream的算子
  • 3.4:持久化
  • 4:部署启动
  • 4.1:yarn的demo
  • 5:日志监控
  • 6:调优
  • 6.1:并行度
  • 1:数据接收并行度
  • 2:数据处理并行度
  • 6.2:序列化
  • 1:RDD缓存级别
  • 2:序列化类
  • 1:java序列化
  • 2:kryo序列化
  • 6.3:接收处理限速
  • 6.4:内存资源调优


1:SparkStreaming编程指南

1:概述

Spark Streaming 是 Spark Core API 的扩展,它支持弹性的,高吞吐的,容错的实时数据流的处理

关于Spark编程的实验总结_spark

2:基本概念

2.1:DStream,DataSet以及DataFrame

DataSet:是一个由特定域的对象组成的强类型集合,可通过功能或关系操作并行转换其中的对象。 每个Dataset还有一个非类型视图,即由多个列组成的DataSet,称为DataFrame。

DataFrame:是一个由多个列组成的结构化的分布式数据集合,等同于关系数据库中的一张表。DataFrame是Spark SQL中的最基本的概念,可以通过多种方式创建,例如结构化的数据集、Hive表、外部数据库或者是RDD。

DStream: 被表示为一系列连续的 RDDs,每个 RDD 包含来自一定的时间间隔的数据。

关于Spark编程的实验总结_spark_02

  • 1:DStream 构建
1:文件流:可实现监控目录文件
	streamingContext.fileStream[KeyClass, ValueClass, InputFormatClass](dataDirectory)
	streamingContext.textFileStream(dataDirectory="hdfs://namenode:8040/logs/")
2:集成kafka,flume等

SparkStreaming集成kafka0.10及高版本

  • 2:DStream的算子操作
map(func)	    每个元素传递给函数func来返回新的DStream 
flatMap(func)	每个输入项可以映射到0个或多个输出项。
filter(func)	通过符合func返回true 的源DStream的记录来返回新的DStream 
repartition(numPartitions)	通过创建更多或更少的分区来更改此DStream中的并行度
reduceByKey(func, [numTasks])	返回一个新的(K,V)对的DStream,其中使用给定的reduce函数聚合每个键的值。
								注意:默认情况下,此操作使用Spark的默认并行任务数(本地模式为2,而在集群模式下,
								此数量由config属性确定spark.default.parallelism)进行分组。您可以传递一个可选numTasks参数来设置不同数量的任务。
transform(func)	通过对源DStream的每个RDD应用RDD-to-RDD函数来返回新的DStream。这可用于在DStream上执行任意的RDD操作,transform该功能非常强大,
  • 3:Dstream的输出算子操作
print()	在运行流应用程序的驱动程序节点上,打印DStream中每批数据的前十个元素。这对于开发和调试很有用。
saveAsTextFiles(prefix, [suffix])		将此DStream的内容另存为文本文件。基于产生在每批间隔的文件名的前缀和后缀:“prefix-TIME_IN_MS [.suffix]”。
saveAsObjectFiles(prefix, [suffix])	将此DStream的内容保存为SequenceFiles序列化Java对象的内容。基于产生在每批间隔的文件名的前缀和 后缀:“前缀TIME_IN_MS [.suffix]”。
saveAsHadoopFiles(prefix, [suffix])	将此DStream的内容另存为Hadoop文件。基于产生在每批间隔的文件名的前缀和后缀:“prefix-TIME_IN_MS [.suffix]”。
foreachRDD(func)	最通用的输出运算符,将函数func应用于从流生成的每个RDD。此功能应将每个RDD中的数据推送到外部系统,例如将RDD保存到文件或通过网络将其写入数据库。请注意,函数func是在运行流应用程序的驱动程序进程中执行的,并且通常在其中具有RDD操作,这将强制计算流RDD。

2.2:rdd算子介绍

rdd算子介绍

2.3:checkpoint检查点

1:checkpoint存储的数据

checkpoint 有两种类型的数据。

Metadata checkpointing - 将定义 streaming 计算的信息保存到容错存储(如 HDFS)中。这用于从运行 streaming 应用程序的 driver 的节点的故障中恢复(稍后详细讨论)。
元数据包括:
	Configuration - 用于创建流应用程序的配置。
	DStream operations - 定义 streaming 应用程序的 DStream 操作集。
	Incomplete batches - 批量的job 排队但尚未完成。
Data checkpointing - 将生成的 RDD 保存到可靠的存储。这在一些将多个批次之间的数据进行组合的 状态 变换中是必需的。
在这种转换中,生成的 RDD 依赖于先前批次的 RDD,这导致依赖链的长度随时间而增加。
为了避免恢复时间的这种无限增加(与依赖关系链成比例),有状态转换的中间 RDD 会定期 checkpoint 到可靠的存储(例如 HDFS)以切断依赖关系链。

2:checkpoint配置

可以通过在保存 checkpoint 信息的容错,可靠的文件系统(例如,HDFS,S3等)中设置目录来启用 checkpoint。

3:使用

实战demo

RD0.foreachRDD((VoidFunction<JavaRDD<ConsumerRecord<String, byte[]>>>) consumerRecordJavaRDD -> {
                String checkPoint = "" + System.currentTimeMillis();
                HasOffsetRanges hasOffsetRanges = (HasOffsetRanges) (consumerRecordJavaRDD.rdd());
                StringBuilder sb = new StringBuilder();
                for (OffsetRange of : hasOffsetRanges.offsetRanges()) {
                    sb.append(of.topic() + "-" + of.partition() + "=" + of.fromOffset() + "\n");
                }
                localCheckPoint.saveCheckPoint(checkPoint, sb.toString());
});

1:基本用法:保存

streamingContext.checkpoint(checkpointDirectory) 
dstream.checkpoint(checkpointInterval)。通常,DStream的5-10个滑动间隔的检查点间隔是一个不错的尝试。

2:如果要使应用程序从 driver 故障中恢复,您应该重写 streaming 应用程序以具有以下行为。

当程序第一次启动时,它将创建一个新的 StreamingContext,设置所有流,然后调用 start()。
当程序在失败后重新启动时,它将从 checkpoint 目录中的 checkpoint 数据重新创建一个 StreamingContext。

3:getOrCreate
如果checkpointDirectory存在,则将根据检查点数据重新创建上下文。如果该目录不存在(即第一次运行),则将contextFactory调用该函数来创建新上下文并设置DStreams

val context = StreamingContext.getOrCreate(checkpointDirectory, functionToCreateContext _)

4:checkpoint和广播变量

无法从Spark Streaming中的检查点恢复累加器和广播变量。如果启用检查点并同时使用“ 累加器”或“ 广播”变量 ,则必须为“ 累加器”和“ 广播”变量创建延迟实例化的单例实例, 以便在驱动程序发生故障重新启动后可以重新实例化它们

3:sparkStreaming开发

3.1:maven依赖引入

1:sparkStreaming依赖

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming_2.11</artifactId>
    <version>2.2.0</version>
</dependency>

2:结合其他数据源的依赖
针对从 Spark Streaming Core API 中不存在的数据源中获取数据,如 Kafka,Flume,Kinesis,你必须添加相应的坐标 spark-streaming-xyz_2.11 到依赖中。例如,有一些常见的依赖如下。

Source(数据源)											Artifact(maven坐标)
Kafka								   				 spark-streaming-kafka-0-8_2.11
Flume	            	                             spark-streaming-flume_2.11
Kinesis	
spark-streaming-kinesis-asl_2.11 [Amazon Software License]

3.2初始化StreamingContext

一个 StreamingContext 对象必须要被创建出来,它是所有的 Spark Streaming 功能的主入口点。
sparkstreaming初始化可以很sparkconf和SparkContext两种进行初始化
方式1:sparkconf
val conf = new SparkConf().setAppName(appName).setMaster(master)
val ssc = new StreamingContext(conf, Seconds(1))
方式2:SparkContext
val sc = SparkContext(master, appName)
val ssc = StreamingContext(sc, 1)

2:参数解释

appName: 参数是展示在集群 UI 界面上的应用程序的名称
master:该streaming程序的部署模式Spark, Mesos or YARN
在实践中,当在集群上运行时,你不会想在应用程序中硬编码 master,而是 使用 spark-submit 来启动应用程序,并且接受该参数。然而,对于本地测试和单元测试,你可以传递 “local[*]” 来运行 Spark Streaming 进程
batch interval:根据您的应用程序和可用的集群资源的等待时间要求进行设置

3.3:DStream 常见操作

1:窗口函数操作

任何窗口操作都需要指定两个参数。
窗口长度 - 窗口的持续时间
滑动间隔 -执行窗口操作的间隔。
这两个参数必须是源DStream的批处理间隔的倍数。

window(windowLength,slideInterval)		返回基于源DStream的窗口批处理计算的新DStream。
countByWindow(windowLength,slideInterval)	返回流中元素的滑动窗口计数。
reduceByWindow(func,windowLength,slideInterval)		返回一个新的单元素流,该流是通过使用func在滑动间隔内聚合流中的元素而创建的。该函数应该是关联的和可交换的,以便可以并行正确地计算它。
reduceByKeyAndWindow(func,windowLength,slideInterval,[ numTasks ])	在(K,V)对的DStream上调用时,返回新的(K,V)对的DStream,其中使用给定的reduce函数func 在滑动窗口中的批处理上汇总每个键的值。注意:默认情况下,此操作使用Spark的默认并行任务数(本地模式为2,而在集群模式下,此数量由config属性确定spark.default.parallelism)进行分组。您可以传递一个可选 numTasks参数来设置不同数量的任务。
reduceByKeyAndWindow(func,invFunc,windowLength, slideInterval,[ numTasks ])	
上面一种更有效的版本,reduceByKeyAndWindow()其中,使用前一个窗口的减少值递增地计算每个窗口的减少值。这是通过减少进入滑动窗口的新数据并“逆向减少”离开窗口的旧数据来完成的。一个示例是在窗口滑动时“增加”和“减少”键的计数。但是,它仅适用于“可逆归约函数”,即具有对应的“逆归约”函数(作为参数invFunc)的归约函数。像in中一样reduceByKeyAndWindow,reduce任务的数量可以通过可选参数配置。请注意,必须启用检查点才能使用此操作。
countByValueAndWindow(windowLength, slideInterval,[ numTasks ])	在(K,V)对的DStream上调用时,返回新的(K,Long)对的DStream,其中每个键的值是其在滑动窗口内的频率。像in中一样 reduceByKeyAndWindow,reduce任务的数量可以通过可选参数配置。

2:join操作

包括leftOuterJoin,rightOuterJoin,fullOuterJoin

3:Dstream的算子

参见1.2.1Dstream

3.4:持久化

RDD持久化
Dstream持久化
与RDD不同,DStream的默认持久性级别将数据序列化在内存中

4:部署启动

配置选项

4.1:yarn的demo

bin/spark-submit还将从中读取配置选项conf/spark-defaults.conf,也可以将配置写在该文件

$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi \
    --master yarn \
    --deploy-mode cluster \
    --driver-memory 4g \
    --executor-memory 2g \
    --executor-cores 1 \
    --queue thequeue \
    examples/jars/spark-examples*.jar \
    10

1:添加依赖jar

--jars my-other-jar.jar,my-other-other-jar.jar \
    my-main-jar.jar \
    app_arg1 app_arg2

2:动态加载sparkconf属性

--conf "spark.executor.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

3:指定app名字

--name "My app"

4:加载配置文件
–files filename

5:日志监控

运行日志:http://:4040
日志也会存储在hdfs的datanode的数据目录下:hadoop/data*/nm/application_ID/
程序大量报错可能会使磁盘写满,程序报错,datanode故障,需要及时清理日志重启程序。

6:调优

调优指南

6.1:并行度

1:数据接收并行度

1:集成替他: task num=批处理间隔/块间隔spark.streaming.blockInterval
2:集成kafka: task num=kafka分区数

2:数据处理并行度

如果在计算的任何阶段使用的并行任务数量不够高,则群集资源可能无法得到充分利用。例如,对于像reduceByKey 和这样的分布式归约操作reduceByKeyAndWindow,并行任务的默认数量由spark.default.parallelism 属性控制。您可以将并行性级别作为参数传递(请参见 PairDStreamFunctions 文档),或将spark.default.parallelism 配置属性设置为更改默认值。

6.2:序列化

1:RDD缓存级别

2:序列化类

包括java序列化和kryo序列化

1:java序列化
2:kryo序列化

kryo介绍 用Kryo序列化都可以减少CPU和内存的开销,比java序列化快10倍以上
1:使用,不注册也可以使用

指定序列化方式:	conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
注册自定义类:	conf.registerKryoClasses(Array(classOf[MyClass1], classOf[MyClass2]))
spark.kryo.classesToRegister	false	如果您使用Kryo序列化,请提供一个逗号分隔的自定义类名称列表,以向Kryo注册。有关更多详细信息,请参见调整指南。
spark.kryo.referenceTracking	treu	使用Kryo序列化数据时是否跟踪对同一对象的引用,如果对象图具有循环,则这是必需的;如果它们包含同一对象的多个副本,则对于提高效率很有用。如果您不是这种情况,可以禁用它以提高性能。
spark.kryo.registrationRequired	false	是否要求向Kryo注册。如果设置为“ true”,则如果未注册的类被序列化,Kryo将引发异常。如果设置为false(默认值),Kryo将与每个对象一起写入未注册的类名称。编写类名称可能会导致大量的性能开销,因此启用此选项可以严格执行以下操作:用户没有从注册中省略类。
spark.kryo.registrator			false	如果您使用Kryo序列化,请提供一个用逗号分隔的类列表,用于向Kryo注册您的自定义类。如果您需要以自定义方式注册类(例如,指定自定义字段序列化程序),则此属性很有用。否则spark.kryo.classesToRegister比较简单。应该将其设置为extends类 。有关更多详细信息,请参见调整指南。 KryoRegistrator
spark.kryo.unsafe				false	是否使用不安全的Kryo串行器。使用基于不安全的IO可以大大提高速度。
spark.kryoserializer.buffer.max	64m	除非另有说明,否则Kryo序列化缓冲区的最大允许大小(以MiB为单位)。它必须大于您尝试序列化的任何对象,并且必须小于2048m。如果在Kryo中收到“超出缓冲区限制”异常,请增加此值。
spark.kryoserializer.buffer		64k	除非另有说明,否则Kryo序列化缓冲区的初始大小,以KiB为单位。请注意,每个工作线程上每个内核将有一个缓冲区。spark.kryoserializer.buffer.max如果需要,此缓冲区将增长

6.3:接收处理限速

SparkConf配置spark.streaming.receiver.maxRate
spark.streaming.kafka.maxRatePerPartition:每个分区最大拉取的条数

6.4:内存资源调优

内存消耗:Web UI中的“ Storage”页面
资源调优