Apache Kafka:如何从Kafka接收最新消息?

时间:2017-08-30 18:13:12

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

我正在使用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配置中设置任何属性以实现相同的功能?

对此的任何帮助将不胜感激。谢谢

4 个答案:

答案 0 :(得分:2)

Kafka消费者api包括方法

Get-ChildItem -Recurse -Filter '*.c'

因此,您可以从消费者那里获得分配的分区,并最终寻找所有分区。 seekToBeginning有类似的方法。

答案 1 :(得分:0)

您可以在连接Kafka时始终生成新的(随机)组ID - 这样您就可以在连接时开始使用新邮件。

答案 2 :(得分:0)

您可以利用两个KafkaConsumer API从分区获取最后一条消息(假设日志压缩不会成为问题):

  1. public Map<TopicPartition, Long> endOffsets(Collection<TopicPartition> partitions):这为您提供给定分区的结束偏移量。请注意,结束偏移量是要传递的下一条消息的偏移量。
  2. 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()