字节架构师:来说说 Kafka 的消费者客户端详解,你都搞懂了吗?

  • 点对点模式基于队列,类似于同一个消费者组中的数据,由生产者发送数据到分区,然后消费者拉取分区的消息进行消费,此时消息只能被同一个消费者组的消费者消费一次。

  • 发布订阅模式模式就是 kafka 中的分区消息可以被不同消费者组的消费者消费。这就是一对多的广播模式应用。

当然,消费者组是一个逻辑的概念,通过客户端参数 group.id 来配置,默认值为空字符串。而消费者并不是逻辑的概念,它是真正消费数据的实体,可以是线程、也可以是一个机器。

好,明白了消费者与消费者组的概念,接下来我们正式打开 消费者客户端的潘多拉魔盒。

二、Kafka 消费者的应用


同样,消费者也是依赖于 Kafak 的客户端,正常的消费逻辑是下面几个步骤:

  • 1、配置消费者客户端参数及创建相应的消费者实例

  • 2、订阅主题

  • 3、拉取消息并消费

  • 4、提交消费位移

  • 5、关闭消费者实例

这里的位移可能我们还不清楚是什么意思,别急,我们后面会讲到,先来看下一个典型的消费者它应该怎么写。

2.1 消费者客户端演示

public class Consumer {

public static void main(String[] args) {

Properties props = new Properties();

props.put(“bootstrap.servers”, “192.168.81.101:9092”);

props.put(“group.id”, “test”); //消费者组

props.put(“key.deserializer”, “org.apache.kafka.common.serialization.StringDeserializer”);

props.put(“value.deserializer”, “org.apache.kafka.common.serialization.StringDeserializer”);

KafkaConsumer consumer = new KafkaConsumer<>(props);

consumer.subscribe(Arrays.asList(“xiaolei2”));

while (true) {

ConsumerRecords records = consumer.poll(100);

for (ConsumerRecord record : records){

System.out.printf(“offset = %d, key = %s, value = %s%n”, record.offset(), record.key(), record.value());

}

}

}

}

2.2 必要参数配置

在创建消费者的时候,Kafka 有 4 个参数 是必填的,比生产者多了一个。

  • bootstrap.servers : 这个参数用来指定连接 Kafka 集群的 broker 地址列表,可以是单个地址,也可以用逗号分割填上 Kafka 集群地址。

  • key.deserializer 和 value. deserializer :因为消息发送的时候将key 和 value 进行序列化生成字节数组,因此消费数据的时候需要反序列化为原来的数据。

  • group.id : 消费者所在组的名称,默认值为 ”“,如果设置为空,则会抛出异常 Exception in thread “main” org.apache.kafka.common.errors.InvalidGroupIdException: To use the group management or offset commit APIs, you must provide a valid group.id in the consumer configuration. 复制代码

2.3 订阅主题与分区

在创建出 consumer 之后,我们需要为它订阅相关的主题,一个消费者可以订阅一个或多个主题。这里可以使用两个 API

  • consumer.subscribe(Collection topics) :指明需要订阅的主题的集合;

  • consumer.subscribe(Pattern pattern) :使用正则来匹配需要订阅的集合。

对于它订阅的是个集合,我们也容易理解,Kafka 可以通过正则表达式 来匹配相关主题,例如下面的这样:

consumer.subscribe(Pattern.compile(“topic-.*”));

但是如果 consumer 重复定义的话,就以后面的为准,下面订阅的就是 xiaolei3 这个主题。

consumer.subscribe(Arrays.asList(“xiaolei2”));

consumer.subscribe(Arrays.asList(“xiaolei3”));

订阅完主题,我们讲讲它怎么定义分区。

直接订阅特定分区。

consumer.assign(Arrays.asList(new TopicPartition(“xiaolei2”,0)));

这里面使用了 assing 方法来订阅特定分区。那如果不知道有哪些分区怎么办呢?

可以使用 KafkaConsumer 的 partitionsFor() 方法用来查询指定主题的元数据信息。

下面这种实现:

consumer.assign(Arrays.asList(new TopicPartition(“xiaolei2”,0)));

ArrayList topicPartitions = new ArrayList<>();

List partitionInfos = consumer.partitionsFor(“xiaolei2”);

for (PartitionInfo partitionInfo : partitionInfos) {

topicPartitions.add(new TopicPartition(partitionInfo.topic(),partitionInfo.partition()));

}

consumer.assign(topicPartitions);

最后,Kafka 中的消费是基于拉取式的,消息的消费分两种,

  • 一个是推送(push):服务端主动把消息发送给消费者,例如微信公众号文章的发送

  • 一个是拉取(poll):消费者主动向服务端发起请求获取。

Kafka 只需要轮询 API 向服务器定时请求数据,一旦消费者订阅了主题,轮询就会处理所有的细节,例如发送心跳、获取数据、分区再平衡等。而我们则处理业务即可。

三、消费位移


3.1 什么是偏移量

对于 Kafka 的分区来说,它的每条消息都有唯一的偏移量,用来展示消息在分区中对应的位置,它是一个单调递增的整数。在 0.9 版本之后 Kafka 的偏移量是存储在 Kafka 的 _consumer_offsets 主题中。消费者在消费完消息之后会向 这个主题中进行 消费位移的提交。消费者在重新启动的时候就会从新的消费位移处开始消费消息。

你可能感兴趣的:(程序员,kafka,linq,分布式)