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 数据接收 ...
随机推荐
- appium+java (六) 手机chrome浏览器操作
一.前言 早之前写过一段时间的appium for native app(即原生app脚本),但尴尬的是从未写过类似的文章,后期有时间我会陆续接着写,近一阶段有时间又把appium捡起来了,由于公司产 ...
- Android下利用zxing类库实现扫一扫
程序源代码及可执行文件下载地址:http://files.cnblogs.com/rainboy2010/zxingdemo.zip zxing,一款无比强大的条码解析类库,下面讲解一下如何利用zxi ...
- redhat7.3 superset的离线安装
superset是一个python 开发的可视化工具,可以与kylin连接进行数据分析,在官网的讲解中,采用了在线安装方式,生产环境中有yum源,但是没有网,不得不采用离线安装方式.(我们先在有网的环 ...
- destoon使用
使用小计 1.判断是否是手机端 {$DT_TOUCH}模板中使用 2.判断句 {if} {/if} 3.表单管理 扩展功能-----表单管理:添加表单---->管理表单选项------> ...
- WebSocketTest 异步通讯,实时返回数据
using System;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;usin ...
- day04 运算符 流程控制 (if while/of)
1. 运算符算数运算符 + - * / int / float :数字类型 # print(10 + 3.1)# print(10 / 3)# print(10 // 3)# print(10 % 3 ...
- cf1133 bcdef
b所有数模k,记录出现次数即可 #include<bits/stdc++.h> using namespace std; int main(){ ]; ]={}; cin>>n ...
- Spring Cloud Eureka简介及原理
Eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务.Spring Cloud将它集成在其子项目spring-cloud-netflix中,以实现Spring Cloud的服务 ...
- 论文阅读笔记十九:PIXEL DECONVOLUTIONAL NETWORKS(CVPR2017)
论文源址:https://arxiv.org/abs/1705.06820 tensorflow(github): https://github.com/HongyangGao/PixelDCN 基于 ...
- 滴水穿石-08IO
1.0 File a:构造方法 package d8; import java.io.File; public class FileGouZao { public static void main(S ...