版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37050372/article/details/83052951
我们之前SparkStreaming整合Kafka的时候用的是傻瓜式的方式-----createStream,但是这种方式的效率很低。而且在kafka 0.10版本之后就不再提供了。
接下来我们使用Kafka直连的方式,这种方式其实是调用Kafka底层的消费数据的API,我们知道,越底层的东西效率也就越高。
使用之前的方式是要连接到zookeeper的,而现在的方式则不需要。
代码如下:
package com.test.sparkStreaming
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.{HashPartitioner, SparkConf}
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.dstream.{DStream, InputDStream}
import org.apache.spark.streaming.kafka010._
import org.apache.spark.streaming.{Seconds, StreamingContext}
object KafkaDirectStream {
val updateFunc = (it : Iterator[(String, Seq[Int], Option[Int])]) => {
it.map{case (w,s,o) => (w,s.sum + o.getOrElse(0))}
}
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setAppName("KafkaDirectStream").setMaster("local[*]")
val ssc: StreamingContext = new StreamingContext(conf,Seconds(5))
ssc.checkpoint("./ck")
//跟Kafka整合(直连方式,调用Kafka底层的消费数据的API)
val brokerList = "marshal:9092,marshal01:9092,marshal02:9092,marshal03:9092,marshal04:9092,marshal05:9092"
val kafkaParams = Map[String,Object](
"bootstrap.servers" -> brokerList,
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "g100",
//这个代表,任务启动之前产生的数据也要读
"auto.offset.reset" -> "earliest",
"enable.auto.commit" -> (false:java.lang.Boolean)
)
val topics = Array("wordcount")
/**
* 指定kafka数据源
* ssc:StreamingContext的实例
* LocationStrategies:位置策略,如果kafka的broker节点跟Executor在同一台机器上给一种策略,不在一台机器上给另外一种策略
* 设定策略后会以最优的策略进行获取数据
* 一般在企业中kafka节点跟Executor不会放到一台机器的,原因是kakfa是消息存储的,Executor用来做消息的计算,
* 因此计算与存储分开,存储对磁盘要求高,计算对内存、CPU要求高
* 如果Executor节点跟Broker节点在一起的话使用PreferBrokers策略,如果不在一起的话使用PreferConsistent策略
* 使用PreferConsistent策略的话,将来在kafka中拉取了数据以后尽量将数据分散到所有的Executor上
* ConsumerStrategies:消费者策略(指定如何消费)
*
*/
val directStream: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream(ssc,
LocationStrategies.PreferConsistent,
ConsumerStrategies.Subscribe[String,String](topics,kafkaParams)
)
val result: DStream[(String, Int)] = directStream.map(_.value()).flatMap(_.split(" "))
.map((_, 1))
.updateStateByKey(updateFunc, new HashPartitioner(ssc.sparkContext.defaultParallelism), true)
result.print()
directStream.foreachRDD(rdd => {
val offsetRange: Array[OffsetRange] = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
val maped: RDD[(String, String)] = rdd.map(record =>(record.key,record.value))
//计算逻辑
maped.foreach(println)
//循环输出
for(o<-offsetRange){
println(s"${o.topic} ${o.partition} ${o.fromOffset} ${o.untilOffset}")
}
})
ssc.start()
ssc.awaitTermination()
}
}
运行结果如下: