我正在使用Scala中的Spark在Kafka使用者应用程序中使用和处理消息。有时,从Kafka消息队列处理消息所需的时间比平常多一些。那时我需要消费最新消息,忽略生产者已经发布但尚未被消费的早期消息。
这是我的消费者代码:
object KafkaSparkConsumer extends MessageProcessor {
def main(args: scala.Array[String]): Unit = {
val properties = readProperties()
val streamConf = new SparkConf().setMaster("local[*]").setAppName("Kafka-Stream")
val ssc = new StreamingContext(streamConf, Seconds(1))
val group_id = Random.alphanumeric.take(4).mkString("dfhSfv")
val kafkaParams = Map("metadata.broker.list" -> properties.getProperty("broker_connection_str"),
"zookeeper.connect" -> properties.getProperty("zookeeper_connection_str"),
"group.id" -> group_id,
"auto.offset.reset" -> properties.getProperty("offset_reset"),
"zookeeper.session.timeout" -> properties.getProperty("zookeeper_timeout"))
val msgStream = KafkaUtils.createStream[scala.Array[Byte], String, DefaultDecoder, StringDecoder](
ssc,
kafkaParams,
Map("moved_object" -> 1),
StorageLevel.MEMORY_ONLY_SER
).map(_._2)
msgStream.foreachRDD { x =>
x.foreach {
msg => println("Message: "+msg)
processMessage(msg)
}
}
ssc.start()
ssc.awaitTermination()
}
}
有没有办法确保消费者总是在消费者应用程序中获取最新消息?或者我是否需要在Kafka配置中设置任何属性以实现相同的功能?
对此的任何帮助将不胜感激。谢谢
答案 0 :(得分:2)
Kafka消费者api包括方法
Get-ChildItem -Recurse -Filter '*.c'
因此,您可以从消费者那里获得分配的分区,并最终寻找所有分区。 seekToBeginning有类似的方法。
答案 1 :(得分:0)
您可以在连接Kafka时始终生成新的(随机)组ID - 这样您就可以在连接时开始使用新邮件。
答案 2 :(得分:0)
您可以利用两个KafkaConsumer API从分区获取最后一条消息(假设日志压缩不会成为问题):
public Map<TopicPartition, Long> endOffsets(Collection<TopicPartition> partitions)
:这为您提供给定分区的结束偏移量。请注意,结束偏移量是要传递的下一条消息的偏移量。public void seek(TopicPartition partition, long offset)
:为每个分区运行此命令,并从上面的调用减去1(假设它大于0)提供其结束偏移量。答案 3 :(得分:0)
是的,您可以将staringOffset设置为最新消费最新消息。
val spark = SparkSession
.builder
.appName("kafka-reading")
.getOrCreate()
import spark.implicits._
val df = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "localhost:9092")
.option("startingOffsets", "latest")
.option("subscribe", topicName)
.load()