【Kafka】消费者Consumer详解

消息消费

消息消费流程

参考:https://mp.weixin.qq.com/s/v6jUK8TIPi1Debfd40GU3w

消费者消费也主要分为两个阶段:

  1. 信息注册阶段,即整个消费者组向集群注册消费信息等
  2. 信息消费阶段,开始信息消息,确保消息可靠性等

信息注册

信息注册流程如下:

在这里插入图片描述

注册流程如下:

  1. 消费者组内所有消费者都会向集群寻找自己的Coordinator(组协调器,消费者后续很多操作都需要发送请求到这个节点)
  2. 找到Coordinator后,所有的Consumer都会向Coordinator发起join group加入消费者组的请求
  3. Coordinator会选择一个最早发起请求的Consumer作为leader Consumer,其他的Consumer作为follower

消息消费

消费流程图如下:

在这里插入图片描述

消费流程如下:

  1. leader消费者根据要消费的Topic及分区情况制定一个消费方案
  2. leader告知给Coordinator,Coordinator再将消费方案告知给各个follower
  3. 消费者到指定分区拉取消息
  4. 消息经过反序列化转为正常的消息对象
  5. 经过拦截器
  6. 消费者提交位移到kafka

消费方式

我们知道消息队列一般有两种实现方式:Push(推模式) 和 Pull(拉模式)。

Kafka Consumer 采用的是主动拉取 Broker 数据进行消费的即 Pull 模式。

为什么不采用Push模式?

如果是选择 Push 模式最大缺点就是 Broker 不清楚 Consumer 的消费速度,且推送速率是 Broker 进行控制的, 这样很容易造成消息堆积,如果 Consumer 中执行的任务操作是比较耗时的,那么 Consumer 就会处理的很慢, 严重情况可能会导致系统 Crash。

为什么采用Pull模式?

如果选择 Pull 模式,这时 Consumer 可以根据自己的情况和状态来拉取数据, 也可以进行延迟处理。但是 Pull 模式也有不足,Kafka 又是如何解决这一问题?**如果 Kafka Broker 没有消息,这时每次 Consumer 拉取的都是空数据, 可能会一直循环返回空数据。 针对这个问题,Consumer 在每次调用 Poll() 消费数据的时候,顺带一个 timeout 参数,当返回空数据的时候,会在 Long Polling 中进行阻塞,等待 timeout 再去消费,直到数据到达。

反序列化

Kafka的broker中所有的消息都是字节数组,消费者获取到消息之后,需要先对消息进行反序列化处理,然后才能交给用户程序消费处理。

消费者的反序列化器包括key的和value的反序列化器:key.deserializervalue.deserializer

反序列化器需要实现接口org.apache.kafka.common.serialization.Deserializer<T>,如下;

package org.apache.kafka.common.serialization;

import java.io.Closeable;
import java.util.Map;
import org.apache.kafka.common.header.Headers;

public interface Deserializer<T> extends Closeable {
   
    default void configure(Map<String, ?> configs, boolean isKey) {
   
    }

    T deserialize(String var1, byte[] var2);

    default T deserialize(String topic, Headers headers, byte[] data) {
   
        return this.deserialize(topic, data);
    }

    default void close() {
   
    }
}

同时kafka也提供了一些默认的反序列化器:

在这里插入图片描述

除了上述提供的,还可以自定义序列化器,只要实现Deserializer接口即可。

import com.lagou.kafka.demo.entity.User; 
import org.apache.kafka.common.serialization.Deserializer;
import java.nio.ByteBuffer;
import java.util.Map;


public class UserDeserializer implements Deserializer<User> {
   
    @Override
    public void configure(Map<String, ?> configs, boolean isKey) {
   
    }

    @Override
    public User deserialize(String topic, byte[] data) {
   
        ByteBuffer allocate = ByteBuffer.allocate(data.length);
        allocate.put(data);
        allocate.flip();
        int userId = allocate.getInt();
        int length = allocate.getInt();
        System.out.println(length);
        String username = new String(data, 8, length);
        return new User(userId, username);
    }

    @Override
    public void close() {
   
    }
}

消费时配置写上我们自定义的反序列化器:

Map<String, Object> configs = new HashMap<>();
...
configs.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, UserDeserializer.class);
KafkaConsumer<String, User> consumer = new KafkaConsumer<String, User>(configs);
consumer.subscribe(Collections.singleton("tp_user_01"));
...

拦截器

消费者在拉取了分区消息之后,经过反序列化器对key和value进行反序列化处理后,消费端设置了拦截器,则需要经过拦截器的处理之后,才能返回给消费者应用程序进行处理。

在这里插入图片描述

拦截器特点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ethan-running

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值