本节介绍一下如何配置Spark Streaming 来接收kafka的数据。有两个方法:
1、老的方法 -使用Receivers 和kafka的高级API
2、新的方法( Spark 1.3 开始引入)-不适用Receivers。这两个方式拥有不同的编程模型,性能特征和语义保证,为了获得更多细节,继续往下读。对于目前的版本的spark。这两个方式都是稳定的。
这个方法使用了一个Receiver 接收数据。这个Receiver 是用kafka 高级的 consumer的api实现的。对于所有的receiver,通过Receiver 接收的kafka的数据会被存储到Spark的executors,然后 Spark Streaming 启动jobs处理数据。
然而 默认配置下,这个方式在失败的情况下回丢失数据(参考 receiver reliability.
)。为了保证零数据丢失,你必须在Spark Streaming (introduced in Spark 1.2)额外的开启Write Ahead Logs。这会同步的把接受的到kafka的数据写入到分布式系统(比如 HDFS) ahead logs 中,因此 所有的数据都可以在失败的时候进行恢复。 参考 Deploying section
以获取更多的关于 Write Ahead Logs.的信息。
下面, 我们讨论下如何在你的streaming的应用中 使用这个方法。
1、Linking: 对于Scala/Java 应用使用SBT/MAven的项目定义,连接到你的streaming的应用使用如下的artifact。
groupId = org.apache.spark
artifactId = spark-streaming-kafka-0-8_2.11
version = 2.2.0
2、编程: 如下所示
import org.apache.spark.streaming.kafka._
val kafkaStream = KafkaUtils.createStream(streamingContext,
[ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume])
你也可以通过使用 createStream 的参数指定key和value的类和以及它们响应的解码的类。参考See the API docsand the example.
需要记住的点
3、 部署
和其他的Spark的应用一样,spark-submit 用来提交你的应用。然而 Scala/java 与python 在细节方面有稍微的不同。
对于Scala和Java的应用,如果你正在使用SBT或者maven管理项目,会把spark-streaming-kafka-0-8_2.11 和他的依赖打包到应用的JAR。需要确保spark-core_2.11 和spark-streaming_2.11 被标记为provided,因为这些在Spark的安装中就已经有了。然后使用spark-submit 提交你的应用(参见主编程指南中的部署部分)。
Python应用没有SBT和maven项目管理,spark-streaming-kafka-0-8_2.11 和它的依赖可以直接添加到Spark 要提交的包中(见应用提交指南)。
./bin/spark-submit --packages org.apache.spark:spark-streaming-kafka-0-8_2.11:2.2.0 ...
或者,你也可以从maven的仓库下载 Maven 的 spark-streaming-kafka-0-8-assembly ,把它加到你要提交 spark-submit 通过--jars的形式。
在Spark1.3中引入了这种新的接收器较少的“直接”方法,以确保更强的端到端保证。该方法不使用接收者接收数据,而是周期性地查询Kafka在每个主题+分区中的最新偏移量,并据此定义每批(batch)处理的偏移范围。当处理数据的作业被启动时,Kafka的简单消费者API用于读取Kafka定义的偏移范围(类似于文件系统中的读取文件)。注意这个功能被引入是Spark1.3 在Scala和java API,Spark 1.4 才提供Python API。
这种方法比基于接收者的方法(即方法1)具有以下优点。
- 链接:这种方法只支持在scala/ java应用程序。你的SBT/Maven项目使用如下的artifact(见链接,在进一步信息的主要编程指南部分)。
groupId = org.apache.spark
artifactId = spark-streaming-kafka-0-8_2.11
version = 2.2.0
- 编程: 在streaming的应用的代码中,引入kafkautils,并创建如下输入dstream。
import org.apache.spark.streaming.kafka._
val directKafkaStream = KafkaUtils.createDirectStream[
[key class], [value class], [key decoder class], [value decoder class] ](
streamingContext, [map of Kafka parameters], [set of topics to consume])
你也可以传入messagehandler到createdirectstream访问messageandmetadata包含有关当前消息元数据,并将它转换为任意类型。请参见API文档和示例。
在Kafka的参数中,您必须指定metadata.broker.list或bootstrap.servers。默认情况下,它将从每个Kafka分区的最新偏移量开始消费。如果你设置的配置auto.offset.reset 参数smallest,它将从最小的偏移处开始消费。
你也可以使用的其他变化kafkautils.createdirectstream,从任意的偏移开始消费。此外,如果您希望访问每个batch中消耗的Kafka偏移量,您可以执行以下操作。
// Hold a reference to the current offset ranges, so it can be used downstream
var offsetRanges = Array.empty[OffsetRange]
directKafkaStream.transform { rdd =>
offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
rdd
}.map {
...
}.foreachRDD { rdd =>
for (o <- offsetRanges) {
println(s"${o.topic} ${o.partition} ${o.fromOffset} ${o.untilOffset}")
}
...
}