基于spark-streaming-kafka-0.10的自定义消费示例
spark版本-2.3.4
spark在2.3.0后已经不推荐使用0.8连接器的。0.10连接器也不支持receiver stream。
但是在学习的过程中,发现新版本的写法与老版本还是出入很大的。如何自定义分区开始读取的偏移量,如何将offset与zookeeper同步,查了下相关资料也比较少,官网对与这块内容也是简单一提。所以尝试着基于源码自己搞清楚,该怎么去做。
简单的创建DirectDStream
这个就是复制官网的代码,后续也是在他的基础上做修改。
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "localhost:9092,anotherhost:9092",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "use_a_separate_group_id_for_each_stream",
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean)
)
val topics = Array("topicA", "topicB")
val stream = KafkaUtils.createDirectStream[String, String](
streamingContext,
PreferConsistent,
Subscribe[String, String](topics, kafkaParams)
)
kafkaParams就是对于Kafka的一些配置信息,这里也不过多描述。
如何创建一个DirectStream
我们来看一下创建流的构造方法
简单解释下这几个入参:
入参 | 含义 |
---|---|
LocationStrategy | 如何去选择合适的执行器来消费 |
ConsumerStrategy | 消费策略 |
PerPartitionConfig | 配置消费速率 |
关于LocationStrategy的官方解释
中文是我自己的理解,如有不对的地方见谅 。
案例中我选择 PreferConsistent
对于ConsumerStrategy的解释
我们看下构造方法
显而易见,offsets就是我想要的,它定义各分区起始位置。
我们再看下TopicPartition类的结构,跟名字一样(topic ,分区号)
PerPartitionConfig的作用
它提供了一个类 DefaultPerPartitionConfig。
会去获取SparkConf下的配置,spark.streaming.kafka.maxRatePerPartition。
既然参数明确了,接下来就开始修改代码
//1.设定topic对应的分区的起始偏移量
val offsetEachPartition = Map(
new TopicPartition("topicA",0) -> 100L
new TopicPartition("topicA",1) -> 200L
)
//2.设定订阅规则
val subscribeRule = Subscribe[String, String](topics, kafkaParams,offsetEachPartition)
//3.设定消费速率
//方式1-在SparkConf中设定 spark.streaming.kafka.maxRatePerPartition
//方式2-继承抽象类实现它的方法
private class UDPerPartitionConfig(numOfMessages:Long) extends PerPartitionConfig(){
override def maxRatePerPartition(topicPartition: TopicPartition): Long = numOfMessages
}
//组装
val stream = KafkaUtils.createDirectStream[String, String](
streamingContext,
PreferConsistent,
subscribeRule,
new UDPerPartitionConfig(10L)
)
//完工
运行时出现一个异常:
序列化问题,ConsumerRecord不能被序列化。这个问题暂时我还不清楚什么导致的。
我的解决方案时采用Kyro序列化,将该类注册进去。
运行结果
确实按照自定义的偏移量来拉取了。代码无误。
下次看看如何将offset同步到zookeeper