【发布时间】:2018-10-10 19:16:04
【问题描述】:
我很确定没有简单的方法可以做到这一点,但这是我的用例:
我有一个 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,但在接下来的微批处理中,它只运行“foreachRDD "声明。
例如,假设 r.nextInt(250) 返回 40。Spark Streaming 作业将连接到 topic_40 并处理其数据。但是在接下来的微批处理中,它仍然会连接到topic_40,并且忽略foreachRDD语句之前的所有命令。
我猜这是意料之中的,因为 foreachRDD 语句之前的代码只在 Spark 驱动程序上运行。
我的问题是,有没有一种方法可以做到这一点,而不必每 5 秒重新启动一次 Spark 应用程序?
谢谢。
【问题讨论】:
-
你不能创建一个所有主题的列表并消费数据吗?
-
@ShankarKoirala ,如果我有 5 到 10 个主题可供消费,这种方法会很好。但是有 250 个,连接到 Kafka brokers 需要很长时间,主要是因为每个 topic 的连接不是并行的,而是顺序的(你可以在这里找到更多关于它的信息stackoverflow.com/a/34448362/4135691)
-
@ShankarKoirala 每个主题都有一个分区并从不同的数据源接收数据。出于组织和可扩展性的目的,以这种方式分隔数据是一种常见的做法。
-
我很想知道为什么你想这样做?您在这里尝试实现的设计模式是什么?
-
@RobinMoffatt,这里是用例:我有 250 个数据源,每个数据源通过 Kafka 生产者将数据发送到 kafka 主题。然后,Spark Streaming 作业每 5 秒从这些主题中消耗一次以处理该数据。但是,并非所有主题在给定的微批次中都有新数据。因此,根据主题偏移量,我确定应该在该微批次中连接哪些主题。我这样做是因为尝试同时连接到所有 250 个 kafka 主题需要的时间太长,而我需要达到的处理时间。
标签: scala apache-spark apache-kafka spark-streaming