064 SparkStream与kafka的集成,主要是编程
这里面包含了如何在kafka+sparkStreaming集成后的开发,也包含了一部分的优化。
一:说明
1.官网
指导网址:http://spark.apache.org/docs/1.6.1/streaming-kafka-integration.html
2.SparkStream+kafka
Use Receiver
内部使用kafka的high lenel consumer API
consumer offset 只能保持到zk/kafka中,只能通过配置进行offset的相关操作
Direct
内部使用的是kafka的simple consumer api
自定义对kafka的offset偏移量进行控制操作
集成依赖pom配置:
二:单Receiver的程序
1.先启动服务
在这里需要启动kafka的生产者
2.程序
package com.stream.it import kafka.serializer.StringDecoder
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.dstream.ReceiverInputDStream
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext} object KafkaWordcount {
def main(args: Array[String]): Unit = {
val conf=new SparkConf()
.setAppName("spark-streaming-wordcount")
.setMaster("local[*]")
val sc=SparkContext.getOrCreate(conf)
val ssc=new StreamingContext(sc,Seconds(15)) /*
def createStream[K: ClassTag, V: ClassTag, U <: Decoder[_]: ClassTag, T <: Decoder[_]: ClassTag](
ssc: StreamingContext,
kafkaParams: Map[String, String],
topics: Map[String, Int],
storageLevel: StorageLevel
): ReceiverInputDStream[(K, V)]
*/
val kafkaParams=Map("group.id"->"stream-sparking-0",
"zookeeper.connect"->"linux-hadoop01.ibeifeng.com:2181/kafka",
"auto.offset.reset"->"smallest"
)
val topics=Map("beifeng"->1)
val dStream=KafkaUtils.createStream[String,String,StringDecoder,StringDecoder](
ssc, //给定sparkStreaming的上下文
kafkaParams, //kafka的参数信息,通过kafka HightLevelComsumerApi连接
topics, //给定读取对应的topic的名称以及读取数据的线程数量
StorageLevel.MEMORY_AND_DISK_2 //数据接收器接收到kafka的数据后的保存级别
).map(_._2) val resultWordcount=dStream
.filter(line=>line.nonEmpty)
.flatMap(line=>line.split(" ").map((_,1)))
.reduceByKey(_+_)
resultWordcount.foreachRDD(rdd=>{
rdd.foreachPartition(iter=>iter.foreach(println))
}) //启动
ssc.start()
//等到
ssc.awaitTermination()
}
}
3.效果
在kafka producer输入内容,将会在控制台上进行展示
三:多Receiver
1.说明
当当个reveiver接收的数据被限制的时候,可以使用多个receiver
2.程序
package com.stream.it import kafka.serializer.StringDecoder
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext} object MulReceiverKafkaWordcount {
def main(args: Array[String]): Unit = {
val conf=new SparkConf()
.setAppName("spark-streaming-wordcount2")
.setMaster("local[*]")
val sc=SparkContext.getOrCreate(conf)
val ssc=new StreamingContext(sc,Seconds(15)) /*
def createStream[K: ClassTag, V: ClassTag, U <: Decoder[_]: ClassTag, T <: Decoder[_]: ClassTag](
ssc: StreamingContext,
kafkaParams: Map[String, String],
topics: Map[String, Int],
storageLevel: StorageLevel
): ReceiverInputDStream[(K, V)]
*/
val kafkaParams=Map("group.id"->"stream-sparking-0",
"zookeeper.connect"->"linux-hadoop01.ibeifeng.com:2181/kafka",
"auto.offset.reset"->"smallest"
)
val topics=Map("beifeng"->4)
val dStream1=KafkaUtils.createStream[String,String,StringDecoder,StringDecoder](
ssc, //给定sparkStreaming的上下文
kafkaParams, //kafka的参数信息,通过kafka HightLevelComsumerApi连接
topics, //给定读取对应的topic的名称以及读取数据的线程数量
StorageLevel.MEMORY_AND_DISK_2 //数据接收器接收到kafka的数据后的保存级别
).map(_._2) val dStream2=KafkaUtils.createStream[String,String,StringDecoder,StringDecoder](
ssc, //给定sparkStreaming的上下文
kafkaParams, //kafka的参数信息,通过kafka HightLevelComsumerApi连接
topics, //给定读取对应的topic的名称以及读取数据的线程数量
StorageLevel.MEMORY_AND_DISK_2 //数据接收器接收到kafka的数据后的保存级别
).map(_._2) //合并dstream
val dStream=dStream1.union(dStream2) val resultWordcount=dStream
.filter(line=>line.nonEmpty)
.flatMap(line=>line.split(" ").map((_,1)))
.reduceByKey(_+_)
resultWordcount.foreachRDD(rdd=>{
rdd.foreachPartition(iter=>iter.foreach(println))
}) //启动
ssc.start()
//等到
ssc.awaitTermination()
}
}
3.效果
一条数据是一个event
这里有两个receiver。
四:Direct
1.说明
直接读取,不存在receiver
不足,kafkaParams指定连接kafka的参数,内部使用的是kafka的SimpleConsumerAPI,所以,offset只能从头或者从尾开始读取,不能设置。
topics:topic的名称
2.程序
package com.stream.it import kafka.serializer.StringDecoder
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext} object DirectKafkaWordcount {
def main(args: Array[String]): Unit = {
val conf=new SparkConf()
.setAppName("spark-streaming-wordcount")
.setMaster("local[*]")
val sc=SparkContext.getOrCreate(conf)
val ssc=new StreamingContext(sc,Seconds(15)) val kafkaParams=Map(
"metadata.broker.list"->"linux-hadoop01.ibeifeng.com:9092,linux-hadoop01.ibeifeng.com:9093,linux-hadoop01.ibeifeng.com:9094",
"auto.offset.reset"->"smallest"
)
val topics=Set("beifeng")
val dStream=KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder](
ssc,
kafkaParams,
topics).map(_._2) val resultWordcount=dStream
.filter(line=>line.nonEmpty)
.flatMap(line=>line.split(" ").map((_,1)))
.reduceByKey(_+_)
resultWordcount.foreachRDD(rdd=>{
rdd.foreachPartition(iter=>iter.foreach(println))
}) //启动
ssc.start()
//等到
ssc.awaitTermination()
}
}
3.效果
没有receiver。
五:Direct实现是累加器管理offset偏移量
1.程序
kafkaParams 中只有这个参数下才能生效。
数据先进行保存或者打印,然后更新accumulable中的offset,然后下一批的dstream进行更新offset。
累加器需要在外面进行定义。
package com.stream.it import scala.collection.mutable
import kafka.common.TopicAndPartition
import kafka.message.MessageAndMetadata
import kafka.serializer.StringDecoder
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{Accumulable, AccumulableParam, SparkConf, SparkContext} object AccumubaleKafkaWordcount {
def main(args: Array[String]): Unit = {
val conf=new SparkConf()
.setAppName("spark-streaming-wordcount")
.setMaster("local[*]")
val sc=SparkContext.getOrCreate(conf)
val ssc=new StreamingContext(sc,Seconds(15))
val accumu = DroppedAccumulable.getInstance(sc) val kafkaParams = Map(
"metadata.broker.list" -> "linux-hadoop01.ibeifeng.com:9092,linux-hadoop01.ibeifeng.com:9093,linux-hadoop01.ibeifeng.com:9094,linux-hadoop01.ibeifeng.com:9095"
) // TODO: 从某一个存储offset的地方读取offset偏移量数据, redis\hbase\其他地方.....
val fromOffsets = Map(
TopicAndPartition("beifeng", 0) -> -1L, // 如果这里给定的偏移量是异常的,会直接从kafka中读取偏移量数据(largest)
TopicAndPartition("beifeng", 1) -> 0L,
TopicAndPartition("beifeng", 2) -> 0L,
TopicAndPartition("beifeng", 3) -> 0L
) val dstream = KafkaUtils.createDirectStream[String, String, kafka.serializer.StringDecoder, kafka.serializer.StringDecoder, String](
ssc, // 上下文
kafkaParams, // kafka连接
fromOffsets,
(message: MessageAndMetadata[String, String]) => {
// 这一块在Executor上被执行
// 更新偏移量offset
val topic = message.topic
val paritionID = message.partition
val offset = message.offset
accumu += (topic, paritionID) -> offset
// 返回value的数据
message.message()
}
) val resultWordCount = dstream
.filter(line => line.nonEmpty)
.flatMap(line => line.split(" ").map((_, 1)))
.reduceByKey(_ + _) resultWordCount.foreachRDD(rdd => {
// 在driver上执行
try {
rdd.foreachPartition(iter => {
// 代码在executor上执行
// TODO: 这里进行具体的数据保存操作
iter.foreach(println)
}) // TODO: 在这里更新offset, 将数据写入到redis\hbase\其他地方.....
accumu.value.foreach(println)
} catch {
case e: Exception => // nothings
}
}) //启动
ssc.start()
//等到
ssc.awaitTermination()
}
}
object DroppedAccumulable {
private var instance: Accumulable[mutable.Map[(String, Int), Long], ((String, Int), Long)] = null def getInstance(sc: SparkContext): Accumulable[mutable.Map[(String, Int), Long], ((String, Int), Long)] = {
if (instance == null) {
synchronized {
if (instance == null) instance = sc.accumulable(mutable.Map[(String, Int), Long]())(param = new AccumulableParam[mutable.Map[(String, Int), Long], ((String, Int), Long)]() {
/**
* 将t添加到r中
*
* @param r
* @param t
* @return
*/
override def addAccumulator(r: mutable.Map[(String, Int), Long], t: ((String, Int), Long)): mutable.Map[(String, Int), Long] = {
val oldOffset = r.getOrElse(t._1, t._2)
if (t._2 >= oldOffset) r += t
else r
} override def addInPlace(r1: mutable.Map[(String, Int), Long], r2: mutable.Map[(String, Int), Long]): mutable.Map[(String, Int), Long] = {
r2.foldLeft(r1)((r, t) => {
val oldOffset = r.getOrElse(t._1, t._2)
if (t._2 >= oldOffset) r += t
else r
})
} override def zero(initialValue: mutable.Map[(String, Int), Long]): mutable.Map[(String, Int), Long] = mutable.Map.empty[(String, Int), Long]
})
}
} // 返回结果
instance
}
}
2.效果
可以将以前的信息打出来。
064 SparkStream与kafka的集成,主要是编程的更多相关文章
- Cassandra与Kafka的集成
Cassandra和Kafka经常一起用于微服务架构中.本文将介绍几种Cassandra和Kafka常见的集成模式. 简介 如果您的开发团队乐于接纳微服务架构的优点,那么您就会了解到,Kafk ...
- Kafka spring 集成
下载配置kafka参考该链接:http://www.cnblogs.com/super-d2/p/4534323.html pom.xml: <dependency> <groupI ...
- Structured Streaming教程(3) —— 与Kafka的集成
Structured Streaming最主要的生产环境应用场景就是配合kafka做实时处理,不过在Strucured Streaming中kafka的版本要求相对搞一些,只支持0.10及以上的版本. ...
- spark Streaming与kafka的集成消费
Spark 2.3.3 Kafka 2.11-1.0.2 Java jdk1.8.0_191 Hbase 1.2.11 from pyspark impo ...
- SpringBoot Kafka 整合集成 示例教程
1.使用IDEA新建工程,创建工程 springboot-kafka-producer 工程pom.xml文件添加如下依赖: <!-- 添加 kafka 依赖 --> <depend ...
- Spark-stream,kafka结合
先列参考文献: Spark Streaming + Kafka Integration Guide (Kafka broker version 0.10.0 or higher):http://spa ...
- Kafka集成SparkStreaming
Spark Streaming + Kafka集成指南 Kafka项目在版本0.8和0.10之间引入了一个新的消费者API,因此有两个独立的相应Spark Streaming包可用.请选择正确的包, ...
- Storm集成Kafka编程模型
原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3974417.html 本文主要介绍如何在Storm编程实现与Kafka的集成 一.实现模型 数据流程: ...
- Spark Streaming之四:Spark Streaming 与 Kafka 集成分析
前言 Spark Streaming 诞生于2013年,成为Spark平台上流式处理的解决方案,同时也给大家提供除Storm 以外的另一个选择.这篇内容主要介绍Spark Streaming 数据接收 ...
随机推荐
- oracle 定时 job
最近在工作中遇到了要在oracle里面创建一个定时job,从远程数据库里面定时把某张表里面的数据更新到本地服务器上某个表里,具体操作: 1.在自己数据库里面先创建一张表test create tabl ...
- layui前端框架
项目中需要弹出层效果,使用了layui前端框架,主要使用了里面的弹出层特效(可以移动) html代码 要给这个标签绑定click方法 <a href='javascript:;' data-me ...
- ant 相关命令
# jmeter-ant A Simple Ant project for JMeter Performance Test # Pre-Requisite* Java 1.7 or above* JM ...
- Walle,一个开源的web代码发布管理系统
前言 Walle 一个web部署系统工具,可能也是个持续发布工具,配置简单.功能完善.界面流畅.开箱即用!支持git.svn版本管理,支持各种web代码发布,静态的HTML,动态PHP,需要编译的JA ...
- Oracle_plsql_开发工具搭建最小化客户端
一:资源下载获取路径: 二:配置方法 1:前提是安装好plsql开发工具 具体安装步骤略 2:配置 简化版的客户端工具. 具体格式:可以参照下文来修改编写使用. orcl_1521 = (DESCRI ...
- Confluence 6 用户目录图例 - 可读写连接 LDAP
上面的图:Confluence 连接到一个 LDAP 目录. https://www.cwiki.us/display/CONFLUENCEWIKI/Diagrams+of+Possible+Conf ...
- 编辑方法分享之如何编辑PDF文件内容
我们现在在工作中会经常使用到PDF文件,还会有遇到需要编辑PDF文件的时候,PDF文件的编辑问题一直是个大难题.很多朋友在面对PDF文件的时候束手无策,不知道该怎么对它进行编辑.下面小编就教给大家一个 ...
- Nginx详解十九:Nginx深度学习篇之进阶高级模块
这里介绍一些最新或者理解起来有一些难度的Nginx模块 一.secure_link_module模块作用原理:1.制定并允许检查请求的链接的真实性以及保护资源免遭未经授权的访问2.限制链接生效周期 配 ...
- linux-umount挂载点无法卸载:device is busy(解决)
umount不了的原因一般是由于有程序有用户在占用 解决方法: 1. 首先查找谁在占用:#fuser /mnt/nfs 得到进程号. 2. 查找进程:#ps –ef|grep 进程 ...
- jQuery 常用的方法
<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...