Spark Streaming与Kafka集成
Spark Streaming与Kafka集成
1、介绍
kafka是一个发布订阅消息系统,具有分布式、分区化、多副本提交日志特点。kafka项目在0.8和0.10之间引入了一种新型消费者API,注意选择正确的包以获得相应的特性。每个版本都是向后兼容的,因此0.8可以兼容0.9和0.10,但是0.10不能兼容早期版本。0.8支持python、Receiver流和Direct流,不支持偏移量提交API以及动态分区订阅,0.10不支持python和Receiver流,支持Direct流、偏移量提交API和动态分区订阅。具体见表格:
spark-streaming-kafka-0-8 | spark-streaming-kafka-0-10 | |
---|---|---|
Broker Version | 0.8.2.1 or higher | 0.10.0 or higher |
API Maturity | 过时 | 稳定 |
支持语言 | scala、java、python | scala、java |
Receiver流 | 支持 | 不支持 |
Direct流 | 支持 | 支持 |
SSL/TLS | 不支持 | 支持 |
偏移量提交API | 不支持 | 支持 |
动态分区订阅 | 不支持 | 支持 |
2、Spark Streaming与kafka集成
0.10的集成方式和0.8类似,提供了在spark streaming 分区和kafka分区的1:1关系,可以访问偏移量和元数据。但由于使用的是新型消费者API,而不是简单API,因此还是有诸多注意事项。
2.1 创建模块引入依赖
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
<version>2.1.0</version>
</dependency>
注意:不要手动添加org.apache.kafka工件依赖,该依赖已经有正确的工件依赖,多个不同版本会导致不兼容。
2.2 实现scala代码
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.kafka010._
import org.apache.spark.streaming.kafka010.LocationStrategies.PreferConsistent
import org.apache.spark.streaming.kafka010.ConsumerStrategies.Subscribe
/**
* Created by Administrator on 2018/3/8.
*/
object SparkStreamingKafkaScala {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
conf.setAppName("kafka")
conf.setMaster("local[*]")
val ssc = new StreamingContext(conf , Seconds(2))
//kafka参数
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "s102:9092,s103:9092",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "g1",
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean)
)
val topics = Array("topic1")
val stream = KafkaUtils.createDirectStream[String, String](
ssc,
PreferConsistent,
Subscribe[String, String](topics, kafkaParams)
)
val ds2 = stream.map(record => (record.key, record.value))
ds2.print()
ssc.start()
ssc.awaitTermination()
}
}
2.3 启动kafka集群
$>xkafka.sh start
2.4 创建主题
创建主题,指定分区数和副本数,分区数和集群的内核数相同,保证最大并发能力,例如有三个节点,每个节点8个和,分区数为3 * 8 = 24,。
$>kafka-topics.sh --zookeeper s102:2181 --create --topic topic1 \
--replication-factor 3 --partitions 8
2.5 启动控制台消费者
$>kafka-console-consumer.sh --zookeeper s102:2181 --topic topic1
2.6 启动控制台生产者
$>kafka-console-producer.sh --broker-list s102:9092 --topic topic1
2.7 在生产者终端输入消息,检查消费者是否能够收到
2.8 启动Spark streaming应用
2.9 查看流的分区
//通过RDD查看分区数 , 分区数为4
stream.foreachRDD(rdd=>{
println(rdd.partitions.length)
})
2.10 查看kafka主题的分区
$>kafka-topics.sh --zookeeper s102:2181 --topic topic1 --describe
运行结果如下:
3、相关参数
3.1 LocationStrategies
新型kafka消费者API会预提取kafka数据到buffer中,因此让Spark在executor上保持缓存的consumer,对于性能来讲就非常重要,而不是每个batch创建新的consumer,选择在执行器上对于给定的主题分区如何调度消费者。位置策略的本意就是控制消费者在哪些节点上开启。
LocationStrategies.PreferConsistent
大多数情况下,选择使用该方式,将在所有executors上均衡分布分区进行调度。
LocationStrategies.PreferBrokers
如果executor和kafka broker位于同一主机,则可以使用该方式,这将优先调度那些分区为leader的分区。
LocationStrategies.PreferFixed
如果在分区间有严重的数据倾斜,可以使用该方式,允许为分区指定特定的位置进行调度。
3.2 ConsumerStrategies
新型kafka消费者API有几种指定主题的方式。
ConsumerStrategies.Assign
允许指定固定的分区集合。
ConsumerStrategies.Subscribe
允许订阅固定的主题集合。
ConsumerStrategies.SubscribePattern
可以使用正则表达式指定主题。
4、使用PreferFixed和Assign组合
指定s102消费主题的所有分区,每个分区下消费特定的偏移量。
import java.net.Socket
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.{Seconds, StreamingContext}
import scala.collection.mutable.ArrayBuffer
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.TopicPartition
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.kafka010._
import org.apache.spark.streaming.kafka010.LocationStrategies.PreferConsistent
import org.apache.spark.streaming.kafka010.ConsumerStrategies.Subscribe
/**
* Created by Administrator on 2018/3/8.
*/
object SparkStreamingKafkaScala {
//发送消息给远程socket
def sendInfo(msg: String, objStr: String) = {
//获取ip
val ip = java.net.InetAddress.getLocalHost.getHostAddress
//得到pid
val rr = java.lang.management.ManagementFactory.getRuntimeMXBean();
val pid = rr.getName().split("@")(0);
//pid
//线程
val tname = Thread.currentThread().getName
//对象id
val sock = new java.net.Socket("s101", 8888)
val out = sock.getOutputStream
val m = ip + "\t:" + pid + "\t:" + tname + "\t:" + msg + "\t:" + objStr + "\r\n"
out.write(m.getBytes)
out.flush()
out.close()
}
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
conf.setAppName("kafka")
//conf.setMaster("spark://s101:7077")
conf.setMaster("local[8]")
val ssc = new StreamingContext(conf, Seconds(5))
//kafka参数
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "s102:9092,s103:9092",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "g1",
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean)
)
//主题分区与主机名的映射,那个主题分区由哪台主机消费
val map = scala.collection.mutable.Map[TopicPartition,String]()
/**************************************************
*********** 一定要使用ip地址 !!!!*****************
**************************************************/
map.put(new TopicPartition("t1" , 0) , "192.168.231.102")
map.put(new TopicPartition("t1" , 1) , "192.168.231.102")
map.put(new TopicPartition("t1" , 2) , "192.168.231.102")
map.put(new TopicPartition("t1" , 3) , "192.168.231.102")
val fix = LocationStrategies.PreferFixed(map) ;
val topics = Array("t1")
//主题分区集合
val tps = scala.collection.mutable.ArrayBuffer[TopicPartition]()
tps.+=(new TopicPartition("t1" , 0))
tps.+=(new TopicPartition("t1" , 1))
tps.+=(new TopicPartition("t1" , 2))
//偏移量集合
val offsets = scala.collection.mutable.Map[TopicPartition,Long]()
offsets.put(new TopicPartition("t1", 0), 3)
offsets.put(new TopicPartition("t1", 1), 3)
offsets.put(new TopicPartition("t1", 2), 0)
//消费者策略,主题分区与偏移集合
val conss = ConsumerStrategies.Assign[String,String](tps , kafkaParams , offsets)
//创建kakfa直向流
val stream = KafkaUtils.createDirectStream[String,String](
ssc,
fix,
ConsumerStrategies.Assign[String, String](tps, kafkaParams, offsets)
)
val ds2 = stream.map(record => {
val t = Thread.currentThread().getName
val key = record.key()
val value = record.value()
val offset = record.offset()
val par = record.partition()
val topic = record.topic()
val tt = (key , value ,offset, par,topic ,t)
sendInfo(tt.toString() ,this.toString)
tt
})
ds2.print()
ssc.start()
ssc.awaitTermination()
}
}
5、手动提交偏移量
将rdd强制转换成CanCommitOffsets,通过该trait进行提交,且只能异步提交,可以指定回调函数对提交结果进行处理。
val stream = KafkaUtils.createDirectStream(...)
//...
//在driver端提交,因为是DStream的方法,DStream不能串行化。
stream.asInstanceOf[CanCommitOffsets].commitAsync(offsets, new OffsetCommitCallback() {
//回调函数
def onComplete(m: java.util.Map[TopicPartition, OffsetAndMetadata], e: Exception) {
if (null != e) {
// error
} else {
// success
}
}
})
6、消费语义
最多一次
at most ,最多消费一次。先提交,后消费。
//先提交
commitAsync()
//后消费
consume()
最少一次
//先消费
consume()
//后提交
commitAsync()
精准一次
//提交偏移量到数据库,不在kafka中
conn.setAutoCommit();
consume()
updateOffset()
conn.commit();
Spark Streaming与Kafka集成的更多相关文章
- Spark Streaming之四:Spark Streaming 与 Kafka 集成分析
前言 Spark Streaming 诞生于2013年,成为Spark平台上流式处理的解决方案,同时也给大家提供除Storm 以外的另一个选择.这篇内容主要介绍Spark Streaming 数据接收 ...
- Spark Streaming和Kafka集成深入浅出
写在前面 本文主要介绍Spark Streaming基本概念.kafka集成.Offset管理 本文主要介绍Spark Streaming基本概念.kafka集成.Offset管理 一.概述 Spar ...
- Spark Streaming on Kafka解析和安装实战
本课分2部分讲解: 第一部分,讲解Kafka的概念.架构和用例场景: 第二部分,讲解Kafka的安装和实战. 由于时间关系,今天的课程只讲到如何用官网的例子验证Kafka的安装是否成功.后续课程会接着 ...
- spark streaming 对接kafka记录
spark streaming 对接kafka 有两种方式: 参考: http://group.jobbole.com/15559/ http://blog.csdn.net/kwu_ganymede ...
- Spark Streaming、Kafka结合Spark JDBC External DataSouces处理案例
场景:使用Spark Streaming接收Kafka发送过来的数据与关系型数据库中的表进行相关的查询操作: Kafka发送过来的数据格式为:id.name.cityId,分隔符为tab zhangs ...
- 【转】Spark Streaming和Kafka整合开发指南
基于Receivers的方法 这个方法使用了Receivers来接收数据.Receivers的实现使用到Kafka高层次的消费者API.对于所有的Receivers,接收到的数据将会保存在Spark ...
- Spark streaming消费Kafka的正确姿势
前言 在游戏项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从kafka中不 ...
- Spark Streaming和Kafka整合保证数据零丢失
当我们正确地部署好Spark Streaming,我们就可以使用Spark Streaming提供的零数据丢失机制.为了体验这个关键的特性,你需要满足以下几个先决条件: 1.输入的数据来自可靠的数据源 ...
- spark streaming 整合 kafka(一)
转载:https://www.iteblog.com/archives/1322.html Apache Kafka是一个分布式的消息发布-订阅系统.可以说,任何实时大数据处理工具缺少与Kafka整合 ...
随机推荐
- http转https的各种应用
http://www.lccee.com/content-57.html https://www.gworg.com/ssl/127.html apach: LoadModule socache_sh ...
- 磁盘 IO 和网络 IO 该如何评估、监控、性能定位和优化?
生产中经常遇到一些IO延时长导致的系统吞吐量下降.响应时间慢等问题,例如交换机故障.网线老化导致的丢包重传:存储阵列条带宽度不足.缓存不足.QoS限制.RAID级别设置不当等引起的IO延时. 一.评估 ...
- 5.监听器(Listener)
1.监听器简介: 监听器主要用来监听对象的创建,属性的变化,是一个实现特定接口的普通Java类. Listener接口与事件对应表: 与 ServletContext 有关 ServletContex ...
- 理解 Spring 事务原理
转载:https://www.jianshu.com/p/4312162b1458 一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事 ...
- OpenCV属性页配置问题~
详细的OpenCV属性页的安装流程,参考这个网站:http://m.bubuko.com/infodetail-793518.html 运行例子时候,如果遇到这个问题,可能配置环境时候出现问题了. 此 ...
- MapReduce的主要的六个类讲解
a.InputFormat类.该类的作用是将输入的文件和数据分割成许多小的split文件, 并将split的每个行通过LineRecorderReader解析成<Key,Value>,通过 ...
- 浅谈jrebel
有个同事提高个jrebel的工具,提起tomcat的热部署方案. jrebel是一款收费的JVM级的热部署工具包. JVM级的热部署也就是说,可以不重启JVM,让修改或添加的类加载到JVM中. 加载器 ...
- Ordering Tasks UVA - 10305(拓扑排序)
在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点. 先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一. 一直做改操作,直到所有的节点都被 ...
- Linux下判断磁盘是SSD还是HDD的几种方法
环境介绍 Fedora release 25 (Twenty Five) 判断方法 方法一 判断cat /sys/block/*/queue/rotational的返回值(其中*为你的硬盘设备名称,例 ...
- SWIG 和 Python——c/c++与脚本交互
C 和 C++ 被公认为(理当如此)创建高性能代码的首选平台.对开发人员的一个常见要求是向脚本语言接口公开 C/C++ 代码,这正是 Simplified Wrapper and Interface ...