Spark Streaming笔记
Spark Streaming学习笔记
liunx系统的习惯
创建hadoop用户
在hadoop根目录(/home/hadoop)上创建如下目录
app 存放所有软件的安装目录
app/tmp 存放临时文件
data 存放测试数据
lib 存放开发用的jar包
software 存放软件安装包的目录
source 存放框架源码
hadoop生态系统 CDH5.7.x
地址:http://archive.cloudera.com/cdh5/cdh/5/
需求:统计主站每个课程访问的客户端,地域信息分布
地域:ip转换 SparkSQL项目实战
客户端:useragent获取 hadoop基础课程
===>如上2个操作:采用离线(Spark/MapReduce)的方式进行统计
项目架构:
采用Flume进行日志收集后放到HDFS上
离线分析结果:Spark/MapReduce
统计结果图形化展示
离线计算和实时计算对比
1.数据来源
离线:HDFS历史数据,数据量比较大
实时:消息队列(KafKa),实时新增/修改记录过来的某一笔数据
2.处理过程
离线:MapReduce:map+reduce
实时:spark(DStream/SS)
3.处理速度
离线:慢
实时:快速
4.进程
离线:启动+销毁
实时:长时间进行处理
实时流处理框架对比
1.Apache Storm
2.Spark Streaming(SparkCore可以进行离线处理)
3.IBM Stream
4.Yahoo!S4
分布式日志收集框架Flume
1.使用脚本拷贝到hadoop集群的机器上,hadoop fs put..../,如何做监控?时效性怎么处理?
2.flume官网:https://flume.apache.org/
Flume是一种分布式的、可靠的、可用的服务,用于有效地收集、聚合和移动大量日志数据。
基于流式数据的简单,灵活的体系结构。具有健壮和容错性,可调可靠性机制和故障转移,恢复机制。
flume使用一个简单的可扩展数据模型,支持在线分析应用程序
Flume架构及核心组件
1.source:收集数据
2.channel:聚集数据将数据存到某个地方例如HDFS
3.sink:输出数据
Flume环境部署
1.将java配置到系统的环境变量中使用命令:~/.bash_profile配置JAVA_HOME的环境变量
2.配置Flume到环境变量,source下使其生效
3.在flume目录下conf文件夹对flume-env.sh添加java_home环境变量配置
4.检测flume是否安装成功flume-ng version在bin目录下可以查询版本
Flume实战
需求1:从指定网络端口采集数据输出到控制台
一个简单的例子给出一个配置文件示例,描述一个单节点Flume部署。
此配置允许用户生成事件并随后将其记录到控制台。
# example.conf: A single-node Flume configuration
使用flume的关键就是写配置文件
1.配置source
2.配置channel
3.配置sink
4.把以上3个组件串联起来
a1表示agent的名称,启动时需要指定agent名称
r1表示source的名称
k1表示sink的名称
c1表示channel的名称
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
a1.sources.r1.type = netcat
a1.sources.r1.bind = hadoop000(主机名称)
a1.sources.r1.port = 44444
# Describe the sink
a1.sinks.k1.type = logger
# Use a channel which buffers events in memory
a1.channels.c1.type = memory
# Bind the source and sink to the channel
a1.sources.r1.channels = c1,注意:一个source可以输出到多个channels
a1.sinks.k1.channel = c1注意:一个channel输出的sink是一个
以上的内容写完后放到flume的conf目录并创建example.conf
启动agent:
$ bin/flume-ng agent \
--name $example \
--conf $FLUME_HOME/conf \
--conf-file $FLUME_HOME/conf/example.conf \
-Dflume.root.logger=INFO,console
使用telent进行测试:telent hadoop000 44444
Event是flume数据传输的基本单元
event=可选的header+byte array
需求2:监控一个文件实时采集新增额数据输出到控制台
配置文件涉及到agent选型,exec source+memory channel+logger sink
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /home/hadoop/data/data1.log
a1.sources.r1.shell = /bin/sh -C
# Describe the sink
a1.sinks.k1.type = logger
# Use a channel which buffers events in memory
a1.channels.c1.type = memory
# Bind the source and sink to the channel
a1.sources.r1.channels = c1,注意:一个source可以输出到多个channels
a1.sinks.k1.channel = c1注意:一个channel输出的sink是一个
以上的内容写完后放到flume的conf目录并创建exec-memory-logger.conf
启动agent:
$ bin/flume-ng agent \
--name $exec-memory-logger \
--conf $FLUME_HOME/conf \
--conf-file $FLUME_HOME/conf/exec-memory-logger.conf \
-Dflume.root.logger=INFO,console
需求3:将A服务器上打的日志实时采集到B服务器
技术选型,
exec source+memory channel+avro sink
avro source+memory channel+logger sink
######################################################
exec-memory-avro.conf
exec-memory-avro.sources = exec-source
exec-memory-avro.sinks = avro-sink
exec-memory-avro.channels = memory-channel
exec-memory-avro.sources.exec-source.type = exec
exec-memory-avro.sources.exec-source.command = tail -F /home/hadoop/data/data1.log
exec-memory-avro.sources.exec-source.shell = /bin/sh -C
exec-memory-avro.sinks.avro-sink.type = avro
exec-memory-avro.sinks.avro-sink.hostname = hadoop000
exec-memory-avro.sinks.avro-sink.port = 44444
exec-memory-avro.channels.c1.type = memory
exec-memory-avro.sources.exec-source.channels = memory-channel
exec-memory-avro.sinks.avro-sink.channel = memory-channel
##############################################
************************************************************
avro-memory-logger.conf
avro-memory-logger.sources = avro-source
avro-memory-logger.sinks = logger-sink
avro-memory-logger.channels = memory-channel
avro-memory-logger.sources.avro-source.type = avro
avro-memory-logger.sources.avro-source.bind = hadoop000
avro-memory-logger.sources.avro-source.port = 44444
avro-memory-logger.sinks.logger-sink.type = logger
avro-memory-logger.channels.memory-channel.type = memory
avro-memory-logger.sources.avro-source.channels = memory-channel
avro-memory-logger.sinks.logger-sink.channel = memory-channel
***************************************************************
启动顺序
先启动agent:avro--memory-logger,因为存在监听端口
$ bin/flume-ng agent \
--name $avro-memory-logger \
--conf $FLUME_HOME/conf \
--conf-file $FLUME_HOME/conf/avro-memory-logger.conf \
-Dflume.root.logger=INFO,console
再启动agent:exec-memory-avro,
$ bin/flume-ng agent \
--name $exec-memory-avro \
--conf $FLUME_HOME/conf \
--conf-file $FLUME_HOME/conf/exec-memory-avro.conf \
-Dflume.root.logger=INFO,console
日志收集过程:
1.机器A上监控一个文件,当我们访问主站是会有用户行为日志记录到access.log中
2.avro sink把新产生的日志输出到对应的avro source指定的hostname和port上
3.通过avro source对应的agent将我们的日志输出到控制台(kafKa)
分布式发布订阅消息系统Kafka
KafKa架构
producer:生产者,就是生产馒头(数据源)
consumer:消费者,就是吃馒头(处理数据)
broker:篮子
topic:主题,相当于给馒头打一个标签(不同的馒头给不同的人吃)
在Kafka部署及使用之前需要先下载和配置zookeeper
zookeeper下载地址:http://archive.cloudera.com/cdh5/cdh/5/zookeeper-3.4.5-cdh5.7.0/
在/.bash_profile文件中添加zookeeper的环境变量使其生效
拷贝conf目录zoo_sample.cfg文件为zoo.cfg并修改dataDir=文件的存储位置,例如:/home/hadoop/app/tmp/zk
启动zookeeper在$ZK_HOME/bin/执行./zkServer.sh start 通过jps命令能查看到QuorumPeerMain进程
通过zkCli.sh 查看zookeeper,只有zk部署正常才能使用KafKa
Kafka部署及使用
下载KafKa并在/.bash_profile添加环境变量使其生效
修改配置文件$KAFKA_HOME/config目录下的serve.properties文件重点项,一个serve.properties文件相当于一个Broker。
1.brroker.id=0
2.listeners=PLAINTEXT://:9092
3.host.name=hadoop000
4.log.dirs=/home/hadoop/app/tmp/Kafka-logs(注:该目录下存放的是Kafka-logs文件夹)
5.zookeeper.connect=hadoop000:2181
1.单节点单Broker的部署及使用
启动Kafka需要在$KAFKA_HOME/bin目录下执行kafka-server-start.sh $KAFKA_HOME/config/serve.properties。
通过jps命令能查看到kafka进程
启动KafKa后可以创建topic,而创建topic首先要指定zookeeper地址
创建topic命令:$KAFKA_HOME/bin目录下执行kafka-topics.sh --create --zookeeper hadoop000:2181 --replication-factor 1 --partitions 1 --topic hello_topic
通过命令$KAFKA_HOME/bin目录下执行kafka-topics.sh --list --zookeeper hadoop000:2181可以查询zookeeper上挂载有多少个topic
以上工作完成后就可以发送消息(创建topic和zookeeper有关系,发送消息和broker-list有关系)
发送消息:要指定broker
$KAFKA_HOME/bin目录下执行kafka-console-producer.sh --broker-list hadoop000:9092 --topic hello_topic
消费消息(接收消息):注意:要指定zookeeper及zookeeper.connect=hadoop000:2181
$KAFKA_HOME/bin目录下执行kafka-console-consumer.sh --zookeeper hadoop000:2181 --topic hello_topic --from-beginning
--from-beginning的使用(有该参数表示从头开始接收消息,会处理启动之前的数据,没有该参数,不会处理启动之前的数据)
查看所有的topic详细信息:$KAFKA_HOME/bin目录下执行kafka-topics.sh --describe --zookeeper hadoop000:2181
查看指定的topic详细信息:$KAFKA_HOME/bin目录下执行kafka-topics.sh --describe --zookeeper hadoop000:2181 --topic hello_topic
2.单节点多Broker的部署及使用
cp config/server.properties config/server-1.properties
cp config/server.properties config/server-2.properties
修改参数
config/server-1.properties:
broker.id=1
listeners=PLAINTEXT://:9093
log.dirs=/home/hadoop/app/tmp/kafka-logs-1
config/server-2.properties:
broker.id=2
listeners=PLAINTEXT://:9094
log.dirs=/home/hadoop/app/tmp/kafka-logs-2
可以用后台的方式进行启动
> bin/kafka-server-start.sh -daemon $KAFKA_HOME/config/server-1.properties & (注:-daemon表示后台启动)
...
> bin/kafka-server-start.sh -daemon $KAFKA_HOME/config/server-2.properties &
...
创建一个topic信息
> bin/kafka-topics.sh --create --zookeeper hadoop000:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic
查看所有的topic详细信息:$KAFKA_HOME/bin目录下执行kafka-topics.sh --describe --zookeeper hadoop000:2181
Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
Topic: my-replicated-topic Partition: 0 Leader: 1(主节点) Replicas(副本系数): 1,2,0 Isr: 1,2,0(Isr是否存活)
kafka容错性是指只要有一个副本正常就不会影响kafka的正常使用
3.多节点多Broker的部署及使用(多机器使用,忽略)
整合Flume和Kafka完成实时数据采集
修改文件
$FLUME_HOME/conf目录下的avro-memory-logger.conf
原本该文件avro-memory-logger.conf是输出到控制台,现将文件拷贝并改名为avro-memory-kafka.conf输出至kafka,并修改添加以下内容
avro-memory-kafka.sources = avro-source
avro-memory-kafka.sinks = kafka-sink
avro-memory-kafka.channels = memory-channel
avro-memory-kafka.sources.avro-source.type = avro
avro-memory-kafka.sources.avro-source.bind = hadoop000
avro-memory-kafka.sources.avro-source.port = 44444
avro-memory-kafka.sinks.kafka-sink.type = org.apache.flume.sink.kafka.KafkaSink
avro-memory-kafka.sinks.kafka-sink.brokerList = hadoop000:9092
avro-memory-kafka.sinks.kafka-sink.topic = hello_topic
avro-memory-kafka.sinks.kafka-sink.batchSize = 5
avro-memory-kafka.sinks.kafka-sink.requiredAcks =1
avro-memory-kafka.channels.memory-channel.type = memory
avro-memory-kafka.sources.avro-source.channels = memory-channel
avro-memory-kafka.sinks.kafka-sink.channel = memory-channel
启动顺序
先启动agent:avro--memory-kafka,因为存在监听端口
$ bin/flume-ng agent \
--name $avro-memory-kafka \
--conf $FLUME_HOME/conf \
--conf-file $FLUME_HOME/conf/avro-memory-kafka.conf \
-Dflume.root.logger=INFO,console
再启动agent:exec-memory-avro,
$ bin/flume-ng agent \
--name $exec-memory-avro \
--conf $FLUME_HOME/conf \
--conf-file $FLUME_HOME/conf/exec-memory-avro.conf \
-Dflume.root.logger=INFO,console
Scala,Maven,Hadoop,HBase,Spark环境搭建,参见其他博客
Spark Streaming入门
spark源码位置:https://github.com/apache/spark/tree/master/examples/src/main
spark-submit使用
To run this on your local machine, you need to first run a Netcat server
要在本地计算机上运行此命令,首先需要运行Netcat服务器
在$SPARK_HOME/bin目录下执行nc -lk 9999
在$SPARK_HOME/bin目录下执行./spark-submit --master local[2] \
--class 指定运行的组类名称就是包名+类名
--name $SPRAK_HOME/examples/jars/spark-examples_2.11-2.2.0.jar 主机名 NetCat的端口号
hadoop000 9999
例如:./spark-submit --master local[2] --class org.apache.spark.examples.streaming.NetworkWordCount --name NetworkWordCount /home/hadoop/app/spark-2.2.0-bin-2.6.0-cdh5.7.0/examples/jars/spark-examples_2.11-2.2.0.jar hadoop000 9999
注意:local[*],*这个值一定要大于1
spark-shell使用
To run this on your local machine, you need to first run a Netcat server
要在本地计算机上运行此命令,首先需要运行Netcat服务器
在$SPARK_HOME/bin目录下执行nc -lk 9999
在$SPARK_HOME/bin目录下执行./spark-shell--master local[2]
测试:
import org.apache.spark.streaming.{Seconds, StreamingContext}
val ssc = new StreamingContext(sc, Seconds(1))
val lines = ssc.socketTextStream("hadoop000",9999)
val words = lines.flatMap(_.split(" "))
val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _)
wordCounts.print()
ssc.start()
ssc.awaitTermination()
Spark Streaming粗粒度工作原理:
Spark Streaming接收到实时数据流,把数据流按照指定的时间段切成一片片小的数据块,然后把小的数据块传给Spark Engine进行处理。
Spark Streaming细粒度工作原理:不清楚有画图
Spark Streaming核心概念
要初始化Spark Streaming程序,必须创建一个StreamingContext对象,它是所有Spark Streaming功能的主要入口点。
必须根据应用程序的延迟要求和可用的群集资源设置批处理间隔
一旦StreamingContext定义好以后,可以做以下操作:
1.通过创建输入DStreams来定义输入源。
2.通过将转换和输出操作应用于DStream来定义流式计算。
3.开始接收数据并使用streamingContext.start()处理它。
4.等待使用streamingContext.awaitTermination()停止处理。
5.可以使用streamingContext.stop()手动停止处理
要点:
一旦启动了上下文,就不能设置或添加新的流式计算。上下文停止后,无法重新启动。在JVM中只能同时激活一个StreamingContext。StreamingContext上的stop()也会停止SparkContext。要仅停止StreamingContext,请将stop()的可选参数stopSparkContext设置为false。只要在创建下一个StreamingContext之前停止前一个StreamingContext(不停止SparkContext),就可以重复使用SparkContext创建多个StreamingContexts。
什么是DStream(Discretized Streams)?
DStream是Spark Streaming提供的基本抽象。
表示连续的数据流,可以是从源接收的输入数据流,也可以是通过转换输入流生成的已处理数据流。
在内部,DStream由一系列连续的RDD表示,这是Spark对不可变分布式数据集的抽象。
DStream中的每个RDD都包含特定的时间间隔的数据
应用于DStream上的任何操作都会转换成底层RDDs上的操作。对DStream操作算子,例如:map/flatmap,其实底层会被翻译为对DStream中的每个RDD都做相同的操作
因为DStream是由不同批次的RDD所构成的
Input DStreams和Receivers
InputDStream是表示从数据源头接收的输入数据流的DStream。
lines是输入DStream,它表示从netcat服务器接收的数据流。
每个输入DStream(文件系统除外)与Receiver(Scala doc,Java doc)对象相关联,该对象从数据源头接收数据并将其存储在Spark的内存中进行处理
Transformation和Output Operations
与RDD类似,transformations允许修改输入DStream中的数据。
DStreams支持普通Spark RDD上可用的许多转换。一些常见的如下
Transformation | Meaning |
---|---|
map(func) | 通过将源DStream的每个元素传递给函数func来返回一个新的DStream. |
flatMap(func) | 与map类似,但每个输入项可以映射到0个或更多输出项. |
filter(func) | 通过仅选择func返回true的源DStream的记录来返回新的DStream. |
repartition(numPartitions) | 通过创建更多或更少的分区来更改此DStream中的并行度级别. |
union(otherStream) | 返回一个新的DStream,包含源DStream和otherDStream中元素的并集. |
count() | 通过计算源DStream的每个RDD中的元素数量,返回单元素RDD的新DStream. |
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函数聚合每个键的值。注意:默认情况下,这使用Spark的默认并行任务数(本地模式为2,在群集模式下,数量由配置属性spark.default.parallelism确定)进行分组。您可以传递可选的numTasks参数来设置不同数量的任务. |
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) | 通过将RDD-to-RDD函数应用于源DStream的每个RDD来返回新的DStream。这可以用于在DStream上执行任意RDD操作. |
updateStateByKey(func) | 返回一个新的“状态”DStream,其中通过在键的先前状态和键的新值上应用给定函数来更新每个键的状态。这可用于维护每个密钥的任意状态数据. |
Output Operations on DStreams
输出操作允许将DStream的数据推送到外部系统,如数据库或文件系统。由于输出操作实际上允许外部系统使用转换后的数据,因此它们会触发所有DStream转换的实际执行(类似于RDD的操作)。定义了以下输出操作。略!!!!
Spark Streaming整合Flume
注:Flume支持从Spark 2.3.0开始就被废弃了。
Spark Streaming整合Kafka
Spark Streaming整合Flume及Kafka的通用流处理