Caused by: kafka.common.OffsetOutOfRangeException

val req = new TopicMetadataRequest(topics.toList, 0)
    
    val getLeaderConsumer = new SimpleConsumer(brokers, 9092, 10000, 10000, "OffsetLookup") // 第一个参数是 kafka broker 的host,第二个是 port
    val res = getLeaderConsumer.send(req)
    val topicMetaOption = res.topicsMetadata.headOption
    val partitions = topicMetaOption match {
      case Some(tm) =>
        tm.partitionsMetadata.map(pm => (pm.partitionId, pm.leader.get.host)).toMap[Int, String] // 将结果转化为 partition -> leader 的映射关系
      case None =>
        Map[Int, String]()
    }


    val bks = partitions.map(pair => pair._2).toSet.mkString(":9092,") + ":9092"
    logger.info("-----------partitions:\n" + partitions)
    logger.info("-----------bks:\n" + bks)
    val kafkaParam = Map(
      "metadata.broker.list" -> bks,
      //"auto.offset.reset" -> "smallest", // default is largest  to consume
      "group.id" -> groupID);
   
    val topicDirs = new ZKGroupTopicDirs(groupID, topic) // 创建一个 ZKGroupTopicDirs 对象,对保存 第一个参数是 kafka broker 的host,第二个是 port
    val zkTopicPath = s"${topicDirs.consumerOffsetDir}" // 获取 zookeeper 中的路径,这里会变成 /consumers/test_spark_streaming_group/offsets/topic_name
    // val wordDStream = KafkaSourceHelper.kafkaStream(ssc, brokers, new ZooKeeperOffsetsStore(zkHosts, zkPath), topic).cache() 
    val zkClient = new ZkClient(zkHosts, Integer.MAX_VALUE, 10000, ZKStringSerializer) // zookeeper 的host 和 ip,创建一个 client
    val children = zkClient.countChildren(s"${topicDirs.consumerOffsetDir}") //查询该路径下是否字节点(默认有字节点为我们自己保存不同 partition 时生成的)
    logger.info("------zkHosts:" + zkHosts)


    var fromOffsets: Map[TopicAndPartition, Long] = Map() //如果 zookeeper 中有保存 offset,我们会利用这个 offset 作为 kafkaStream 的起始位置


    logger.info("------children:" + children)


    // 获取offset 创建kafkaStream: InputDStream 
    var kafkaStream: InputDStream[(String, String)] = null
    if (children > 0) { //如果保存过 offset,这里更好的做法,还应该和  kafka 上最小的 offset 做对比,不然会报 OutOfRange 的错误
      for (i <- 0 until children) {


        val partitionOffset = zkClient.readData[String](s"${topicDirs.consumerOffsetDir}/${i}")
        val tp = TopicAndPartition(topic, i)


        val requestMin = OffsetRequest(Map(tp -> PartitionOffsetRequestInfo(OffsetRequest.EarliestTime, 1)))
        // Manager Offset:
        // this default use the smallest offset from where to consume ,if you want to manager 
        // offset ,another choice is manually commit offset by hand in zookeeper client or use java API 
        // Here SimpleConsumer constructor need every partition leader not fixed broker.
        val consumerMin = new SimpleConsumer( partitions(i), 9092, 10000, 10000, "getMinOffset") //注意这里的 broker_host,因为这里会导致查询不到,解决方法在下面
        val curOffsets = consumerMin.getOffsetsBefore(requestMin).partitionErrorAndOffsets(tp).offsets
        var nextOffset = partitionOffset.toLong


        // if offset is less than zk store ,use zk offset otherwise use the minimum offset get from each partition
        // 通过比较从 kafka 上该 partition 的最小 offset 和 zk 上保存的 offset,进行选择
        if (curOffsets.length > 0 && nextOffset < curOffsets.head) {
        // logger.info("----------curOffsets.head:" + curOffsets.head +"---nextOffset:" +nextOffset )
        nextOffset = curOffsets.head
        }


        fromOffsets += (tp -> nextOffset) //设置正确的 offset,这里将 nextOffset 设置为 0(0 只是一个特殊值),可以观察到 offset 过期的现象
        logger.info("get from zk topic[" + topic + "] partition[" + i + "] offset[" + partitionOffset + "] @@@@@@")
        logger.info("----------fromOffsets:" + fromOffsets)
      }
      logger.info("------------------- createDirectStream from zk offset -------")
      //这个会将 kafka 的消息进行 transform,最终 kafak 的数据都会变成 (topic_name, message) 这样的 tuple
      val messageHandler = (mmd: MessageAndMetadata[String, String]) => (mmd.topic, mmd.message())


      kafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder, (String, String)](ssc, kafkaParam, fromOffsets, messageHandler)
    } else {
      logger.info("------------------- chilern <=0 createDirectStream -------")
      kafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParam, topics) //如果未保存,根据 kafkaParam 的配置使用最新或者最旧的 offset
    }


     logger.warn("--------brokers:" + brokers)


    var offsetRanges = Array[OffsetRange]()
    val disDStream = kafkaStream.transform { rdd =>
      offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges //得到该 rdd 对应 kafka 的消息的 offset
      rdd

    }


其他信息参阅 :http://blog.csdn.net/kk303/article/details/52767260

java版本offset 获取 :http://blog.csdn.net/rongyongfeikai2/article/details/50727661


http://blog.csdn.net/rongyongfeikai2/article/details/49784785


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的引用内容,报错信息显示了一个`java.lang.ClassNotFoundException`异常,异常信息中指出了缺少`org.apache.commons.logging.Log`类。这个异常通常发生在Java应用程序中,当应用程序无法找到所需的类时会抛出该异常。 对于你提到的`Caused by: java.lang.ClassNotFoundException: org.apache.kafka.common.serialization.ExtendedDeserializer`异常,它表示在你的应用程序中无法找到`org.apache.kafka.common.serialization.ExtendedDeserializer`类。这可能是由于缺少相关的依赖库或配置问题导致的。 解决这个问题的方法是确保你的应用程序的类路径中包含了所需的类。你可以尝试以下几种方法来解决这个问题: 1. 确保你的项目中包含了`org.apache.commons.logging.Log`类的依赖库。你可以在项目的构建文件(如`pom.xml`或`build.gradle`)中添加相关的依赖项,以确保该类可用。 2. 检查你的应用程序的配置文件,确保正确配置了相关的类路径。你可以查看应用程序的启动脚本或配置文件,例如`catalina.sh`或`web.xml`,以确保正确设置了类路径。 3. 如果你使用的是Java开发工具(如Eclipse或IntelliJ IDEA),请确保你的项目设置中包含了所需的类。你可以检查项目的构建路径或依赖项设置,以确保相关的类被正确引入。 请注意,具体的解决方法可能因你的应用程序和环境而异。如果以上方法都无法解决问题,你可能需要进一步调查并查找其他可能的原因。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mtj66

看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值