Streaming和Kafka整合

概述

Kafka项目在0.8和0.10版本之间引入了一个新的消费者api,因此有两个单独的相应的Spark流媒体包。请为您的服务器和所需的功能选择正确的包;注意,0.8集成与后面的0.9和0.10代理兼容,但0.10集成与前面的代理不兼容。

以上是spark官方文档给出的介绍

更多详情可以参考官方文档:http://spark.apache.org/docs/2.2.0/streaming-kafka-integration.html

想了解关于Kafka的更多信息可以参考文章:

【Kafka】消息队列相关知识

【Kafka】Kafka集群环境搭建

【Kafka】Kafka集群基础操作!新手上路必备~

【Kafka】Kafka简单介绍



SparkStreaming一般情况下更多地会和Kafka进行整合,而非Flume,因为Kafka可以实现数据的限流。

从上图和官方文档可以了解到,SparkStreaming和Kafka整合有两个大版本:0.8版本0.10版本



0.8版本接收数据有两种方式:

Receiver DStream —— 是使用HighLevel API(高阶API) 进行消费,每隔一段时间就将offset值保存在ZooKeeper中,消费模式为at least once模式,有可能会造成重复消费的情况

Direct DStream —— 使用LowLevel API(低阶 API) 进行消费,offset值保存在Kafka自带的默认topic中,每次消费都默认从最新的offset值进行消费,消费模式为at most once,可能会造成数据丢失的情况



0.10版本只有一种接收数据的方式:

Direct DStream —— 也是使用LowLevel API 进行消费,不过配合手动提交offset,实现exactly once消费模式,尽量避免重复消费和数据丢失的情况


使用0.8版本下Receiver DStream接收数据进行消费

步骤

一、启动Kafka集群

必须安装了JDK和ZooKeeper,并保证Zookeeper服务正常启动

在三台机器都后台启动kafka服务

cd /export/servers/kafka_2.11-1.0.0/

bin/kafka-server-start.sh config/server.properties > /dev/null 2>&1 &
二、创建maven工程,导入jar包
<properties>
<scala.version>2.11.8</scala.version>
<spark.version>2.2.0</spark.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-8_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-streaming -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.5</version>
</dependency> <dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-hive_2.11</artifactId>
<version>2.2.0</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency> </dependencies>
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<!-- <verbal>true</verbal>-->
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<arg>-dependencyfile</arg>
<arg>${project.build.directory}/.scala_dependencies</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass></mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
三、创建一个kafka的topic
bin/kafka-topics.sh  --create --partitions 3 --replication-factor 2 --topic sparkafka --zookeeper node01:2181,node02:2181,node03:2181
四、启动kafka的Producer
bin/kafka-console-producer.sh --broker-list node01:9092,node02:9092,node03:9092 --topic sparkafka
五、开发代码
package cn.itcast.sparkstreaming.demo5_08

import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.streaming.kafka.KafkaUtils import scala.collection.immutable object SparkKafkaReceiverDStream {
def main(args: Array[String]): Unit = { //获取SparkConf
val sparkConf: SparkConf = new SparkConf().setAppName("SparkKafkaReceiverDStream").setMaster("local[6]").set("spark.driver.host", "localhost")
//获取SparkContext
val sparkContext = new SparkContext(sparkConf)
//设置日至等级
sparkContext.setLogLevel("WARN")
//获取StreamingContext
val streamingContext = new StreamingContext(sparkContext, Seconds(5)) //获取zkQuorum
val zkQuorum = "node01:2181,node02:2181,node03:2181"
//获取topics,开启三个线程
val topics = Map("sparkafka" -> 3) /**
* 使用 1 to 3开启三个线程消费kafka三个分区中的数据
* IndexedSeq 表示里面存放的各个分区的数据
*/
val receiverDStream: immutable.IndexedSeq[ReceiverInputDStream[(String, String)]] = (1 to 3).map(x => {
/**
* Create an input stream that pulls messages from Kafka Brokers. | 创建一个从Kafka代理获取消息的输入流。
* ssc StreamingContext object | StreamingContext对象
* zkQuorum Zookeeper quorum (hostname:port,hostname:port,..) | zookeeper quorum配置
* groupId The group id for this consumer | 次消费者的组名
* topics Map of (topic_name to numPartitions) to consume. Each partition is consumed
* in its own thread
* Map(topic_name -> numPartitions).每个分区都在自己的线程中使用
* DStream of (Kafka message key, Kafka message value)
*/
val stream: ReceiverInputDStream[(String, String)] = KafkaUtils.createStream(streamingContext, zkQuorum, "ReceiverDStreamGroup", topics)
stream
})
// 将各个分区的数据合并到一起
val union: DStream[(String, String)] = streamingContext.union(receiverDStream)
//此时拿到的数据是key,value对的形式,value是我们需要的数据
val value: DStream[String] = union.map(x => x._2)
//打印接收到的数据
value.print() streamingContext.start()
streamingContext.awaitTermination() }
}

使用0.8版本下Direct DStream接收数据进行消费

开发代码

import kafka.serializer.StringDecoder
import org.apache.spark.streaming.dstream.{DStream, InputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.streaming.kafka.KafkaUtils object SparkKafkaDirectDStream {
def main(args: Array[String]): Unit = {
//获取SparkConf
val sparkConf: SparkConf = new SparkConf().setAppName("SparkKafkaDirectDStream").setMaster("local[6]").set("spark.driver.host", "localhost")
//获取SparkContext
val sparkContext = new SparkContext(sparkConf)
//设置日志级别
sparkContext.setLogLevel("WARN")
//获取StreamingContext
val streamingContext = new StreamingContext(sparkContext, Seconds(5))
//配置kafka相关参数
val kafkaParams = Map("metadata.broker.list" -> "node01:9092,node02:9092,node03:9092", "group.id" -> "Kafka_Direct") val topics = Set("sparkafka") /**
* 所需泛型和参数
* [K: ClassTag, type of Kafka message key
* V: ClassTag, type of Kafka message value
* KD <: Decoder[K]: ClassTag, type of Kafka message key decoder
* VD <: Decoder[V]: ClassTag] ( type of Kafka message value decoder
* ssc: StreamingContext, StreamingContext object
* kafkaParams: Map[String, String],
* topics: Set[String]) Names of the topics to consume
*/
val resultDStream: InputDStream[(String, String)] = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](streamingContext, kafkaParams, topics)
//key是null,value是需要的值
val value: DStream[String] = resultDStream.map(x => x._2)
//打印value
value.print() streamingContext.start()
streamingContext.awaitTermination()
} }

使用0.10版本下Direct DStream接收数据进行消费

注意事项

要把pom.xml中0.8版本的包注释掉,把项目中以上两个object注释或者删掉

步骤

一、添加jar包
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
<version>2.2.0</version>
</dependency>
二、开发代码
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.streaming.dstream.InputDStream
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.streaming.kafka010.{CanCommitOffsets, ConsumerStrategies, ConsumerStrategy, HasOffsetRanges, KafkaUtils, LocationStrategies, LocationStrategy, OffsetRange} object NewSparkKafkaDirectDStream {
def main(args: Array[String]): Unit = {
//获取SparkConf
val sparkConf: SparkConf = new SparkConf().setAppName("NewSparkKafkaDirectDStream").setMaster("local[6]").set("spark.driver.host", "localhost")
//获取SparkContext
val sparkContext = new SparkContext(sparkConf)
//设置日志级别
sparkContext.setLogLevel("WARN")
//获取StreamingContext
val streamingContext = new StreamingContext(sparkContext, Seconds(5)) /*
sealed abstract class LocationStrategy
sealed类表示密封类,需要调用LocationStrategy伴生对象的方法
*/
//PreferConsistent: Use this in most cases, it will consistently distribute partitions across all executors. | 在大多数情况下,它会在所有执行器之间一致地分配分区。
val locationStrategy: LocationStrategy = LocationStrategies.PreferConsistent
//需要参数consumerStrategy,就调用其伴生对象中的subscribe方法
/*
topics: Iterable[jl.String],
kafkaParams: collection.Map[String, Object]
*/
val topics: Array[String] = Array("sparkafka")
//创建topic
val brokers = "node01:9092,node02:9092,node03:9092"
val sourcetopic = "sparkafka";
//创建消费者组
var group = "sparkafkaGroup"
//消费者配置
val kafkaParam = Map(
"bootstrap.servers" -> brokers, //用于初始化链接到集群的地址
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
//用于标识这个消费者属于哪个消费团体
"group.id" -> group,
//如果没有初始化偏移量或者当前的偏移量不存在任何服务器上,可以使用这个配置属性
//可以使用这个配置,latest自动重置偏移量为最新的偏移量
"auto.offset.reset" -> "latest",
//如果是true,则这个消费者的偏移量会在后台自动提交
"enable.auto.commit" -> (false: java.lang.Boolean)
);
val consumerStrategy: ConsumerStrategy[String, String] = ConsumerStrategies.Subscribe[String, String](topics, kafkaParam) /**
* 所需参数如下:
* ssc: StreamingContext,
* locationStrategy: LocationStrategy,
* consumerStrategy: ConsumerStrategy[K, V]
*/
val resultStream: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream(streamingContext, locationStrategy, consumerStrategy) //循环遍历每一个RDD,一个RDD中有多个分区,每个分区中有多条数据
resultStream.foreachRDD(iter => {
//判断RDD中是否有数据,如果大于0就是有数据
if (iter.count() > 0) {
//使用foreach,获取到rdd中的每一条数据,并进行处理
iter.foreach(line => {
//key为null,value为我们需要的数据
val value: String = line.value()
//打印数据
println(value)
})
/*
RDD中每处理完一批数据,就手动提交这批数据的offset
利用asInstanceOf将iter强转为HasOffsetRanges,
*/
val ranges: Array[OffsetRange] = iter.asInstanceOf[HasOffsetRanges].offsetRanges
//将resultStream强转为CanCommitOffsets,进行异步提交
resultStream.asInstanceOf[CanCommitOffsets].commitAsync(ranges)
}
})
streamingContext.start()
streamingContext.awaitTermination()
}
}

【Spark】SparkStreaming和Kafka的整合的更多相关文章

  1. 图解SparkStreaming与Kafka的整合,这些细节大家要注意!

    前言 老刘是一名即将找工作的研二学生,写博客一方面是复习总结大数据开发的知识点,一方面是希望帮助更多自学的小伙伴.由于老刘是自学大数据开发,肯定会存在一些不足,还希望大家能够批评指正,让我们一起进步! ...

  2. SparkStreaming和Kafka的整合

    当我们正确地部署好Spark Streaming,我们就可以使用Spark Streaming提供的零数据丢失机制.需要满足以下几个先决条件: 1.输入的数据来自可靠的数据源和可靠的接收器: 2.应用 ...

  3. 【转】Spark Streaming和Kafka整合开发指南

    基于Receivers的方法 这个方法使用了Receivers来接收数据.Receivers的实现使用到Kafka高层次的消费者API.对于所有的Receivers,接收到的数据将会保存在Spark ...

  4. Spark Streaming和Kafka整合开发指南(二)

    在本博客的<Spark Streaming和Kafka整合开发指南(一)>文章中介绍了如何使用基于Receiver的方法使用Spark Streaming从Kafka中接收数据.本文将介绍 ...

  5. Spark Streaming和Kafka整合开发指南(一)

    Apache Kafka是一个分布式的消息发布-订阅系统.可以说,任何实时大数据处理工具缺少与Kafka整合都是不完整的.本文将介绍如何使用Spark Streaming从Kafka中接收数据,这里将 ...

  6. 【Spark】SparkStreaming与flume进行整合

    文章目录 注意事项 SparkStreaming从flume中poll数据 步骤 一.开发flume配置文件 二.启动flume 三.开发sparkStreaming代码 1.创建maven工程,导入 ...

  7. SparkStreaming和Kafka基于Direct Approach如何管理offset实现exactly once

    在之前的文章<解析SparkStreaming和Kafka集成的两种方式>中已详细介绍SparkStreaming和Kafka集成主要有Receiver based Approach和Di ...

  8. SparkStreaming与Kafka,SparkStreaming接收Kafka数据的两种方式

    SparkStreaming接收Kafka数据的两种方式 SparkStreaming接收数据原理 一.SparkStreaming + Kafka Receiver模式 二.SparkStreami ...

  9. Spark streaming消费Kafka的正确姿势

    前言 在游戏项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从kafka中不 ...

随机推荐

  1. Personal Photo Management Application

    Customer Problems & Needs People may take a large number of photos and their phone don't have en ...

  2. Linux下安装python3环境搭建

    Linux下python3环境搭建 Linux安装软件有哪些方式? rpm软件包 手动安装 拒绝此方式 需要手动解决依赖关系 yum自动化安装 自动处理依赖关系 非常好用 源代码编译安装,可自定义的功 ...

  3. 爬虫需要登陆怎么办?这份python登陆代码请收下

    模拟登陆思路 通过selenium中的webdriver控制浏览器登录目标网站,然后获取模拟登陆需要的Cookie,再利用此Cookie来达到登录的效果.本次我们使用webdriver来驱动火狐浏览器 ...

  4. weblogic漏洞(一)----CVE-2017-10271

    WebLogic XMLDecoder反序列化漏洞(CVE-2017-10271) 0x01 漏洞原因: Weblogic的WLS Security组件对外提供webservice服务,其中使用了XM ...

  5. windows下常用快捷指令记忆

    快速打开环境变量窗口 sysdm.cpl --系统设置 快速打开远程桌面程序 mstsc ---Microsoft terminal services client 快速打开事件查看器 eventvw ...

  6. C# 基础知识系列- 13 常见类库介绍(二)日期时间类

    0. 前言 上一篇内容介绍了Console类和Math类,这篇内容着重介绍一下C#中时间日期的处理方式. 上一篇勘误: 上一篇中关于静态类没有构造函数,这一表述有误.正确的说法是C#中静态类不包含常规 ...

  7. tensorflow1.0 placeholder占位符

    import tensorflow as tf #(tf.float32,[2,2]) input1 = tf.placeholder(tf.float32) input2 = tf.placehol ...

  8. 文件上传漏洞(pikachu)

    文件上传漏洞 文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像,附件等等.当用户点击上传按钮后,后台会对上传的文件进行判断,比如是否是指定的类型.后缀名.大小等等,然后将其按照设 ...

  9. 怎么break java8 stream的foreach

    目录 简介 使用Spliterator 自定义forEach方法 总结 怎么break java8 stream的foreach 简介 我们通常需要在java stream中遍历处理里面的数据,其中f ...

  10. Scala的Higher-Kinded类型

    Scala的Higher-Kinded类型 Higher-Kinded从字面意思上看是更高级的分类,也就是更高一级的抽象.我们先看个例子. 如果我们要在scala中实现一个对Seq[Int]的sum方 ...