如何在每批Spark Streaming作业中使用不同的Kafka主题?

时间:2018-04-30 16:46:29

标签: scala apache-spark apache-kafka spark-streaming

我很确定没有简单的方法可以做到这一点,但这是我的用例:

我有一个Spark Streaming作业(版本2.1.0),每个微批次的持续时间为5秒。

我的目标是在每个微分钟间隔消耗来自1个不同主题的数据,总共250个Kafka主题。您可以将下面的代码作为一个简单示例:

 val groupId:String = "first_group"
 val kafka_servers:String =  "datanode1:9092,datanode2:9092,datanode3:9092"

 val ss:SparkSession = SparkSession.builder().config("spark.streaming.unpersist","true").appName("ConsumerStream_test").getOrCreate()
 val ssc:StreamingContext= new StreamingContext(ss.sparkContext,Duration(5000))

val kafka_parameters:Map[String,Object]=Map(
"bootstrap.servers"       -> kafka_servers,
"key.deserializer"        -> classOf[StringDeserializer],
"value.deserializer"      -> classOf[ByteArrayDeserializer],
"heartbeat.interval.ms"   -> (1000:Integer),
"max.poll.interval.ms"    -> (100:Integer),
"enable.auto.commit"      -> (false: java.lang.Boolean),
"autoOffsetReset"         -> OffsetResetStrategy.EARLIEST,
//"connections.max.idle.ms" -> (5000:Integer),
"group.id"                -> groupId
)

val r = scala.util.Random
val kafka_list_one_topic=List("topic_"+ r.nextInt(250))

val consumer:DStream[ConsumerRecord[String,Array[Byte]]] = KafkaUtils.createDirectStream(ssc, LocationStrategies.PreferBrokers, ConsumerStrategies.
Subscribe[String, Array[Byte]](kafka_list_one_topic , kafka_parameters))

consumer.foreachRDD( eachRDD => {
     // DOING SOMETHING WITH THE DATA...
  })
ssc.start()
ssc.awaitTermination()

但是这种方法的问题在于Spark只会运行初始代码(foreachRDD命令之前的所有内容)一次,以便创建Kafka消费者DStream,但是在下面的微批处理中,它只运行&# 34; foreachRDD"言。

作为一个例子,让我们说r.nextInt(250)返回40. Spark Streaming作业将连接到topic_40并处理其数据。但是在下一个微批次中,它仍将连接到topic_40,并忽略foreachRDD语句之前的所有命令。

我想这是预期的,因为foreachRDD语句之前的代码只在Spark驱动程序上运行。

我的问题是,有没有办法我可以做到这一点,而不必每5秒重新启动一个Spark应用程序?

谢谢。

1 个答案:

答案 0 :(得分:0)

我的方法非常简单,如果你想让它真正随机并且不关心任何其他后果,可以将kafka_list_one_topic作为一个可变变量并在流代码中进行更改。

val r = scala.util.Random
var kafka_list_one_topic=List("topic_"+ r.nextInt(250))

val consumer:DStream[ConsumerRecord[String,Array[Byte]]] = 
KafkaUtils.createDirectStream(ssc, LocationStrategies.PreferBrokers, 
ConsumerStrategies.
Subscribe[String, Array[Byte]](kafka_list_one_topic , kafka_parameters))

consumer.foreachRDD( eachRDD => {
 // DOING SOMETHING WITH THE DATA...
 kafka_list_one_topic=List("topic_"+ r.nextInt(250))
 })
ssc.start()
ssc.awaitTermination()