Java实现Kafka消费者及消息异步回调方式

Kafka 在创建消费者进行消费数据时,由于可以理解成为是一个kafka 的单独线程,所以在Kafka消费数据时想要在外部对消费到的数据进行业务处理时是获取不到的,所以就需要实现一个消息回调的接口来进行数据的保存及使用。

消息回调接口实现代码如下

/**
 * 消息队列接收消息回调
 */
public interface TestCallBack {
    /**
     * 消息队列接收消息回调
     *
     * @param s 消息列表
     */
    void callBack(String s);
}

Kafka消费者代码实现如下

public class KafkaTest extends Thread{

    private String topic;

    private String ip;

    private TestCallBack testCallBack;

    /**
     * kafka停止消费标识
     */
    public static Map<String, Boolean> kafka = new ConcurrentHashMap<>();

    public KafkaTest(String topic, String ip, TestCallBack testCallBack){
        this.topic = topic;
        this.ip = ip;
        this.testCallBack = testCallBack;
    }
    public void run(){
        Map<String, Object> props = new HashMap<>();
        props.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString());
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, ip);
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
        KafkaConsumer<String, String> indexKafkaConsumer = new KafkaConsumer<>(props);
        indexKafkaConsumer.subscribe(Arrays.asList(topic));
        KafkaTest.kafka.put(ip+topic, true);
        while (kafka.get(ip+topic)){
            ConsumerRecords<String, String> poll = indexKafkaConsumer.poll(Duration.ofMillis(1000));
            for (ConsumerRecord<String, String> consumerRecord : poll) {
                String value = consumerRecord.value();
                testCallBack.callBack(value);
            }
        }
    }
}

其中

 ConsumerConfig.GROUP_ID_CONFIG 为消费者组Id  不同的消费者组每次消费都是新数据否则会出现消费者1消费到的数据以后 消费者2消费不到数据的情况

ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG 为自动提交offset

ConsumerConfig.AUTO_OFFSET_RESET_CONFIG 为设置消费顺序是否重头开始消费

三种情况如下

latest (默认)
earliest
none
三者均有共同定义:
对于同一个消费者组,若已有提交的offset,则从提交的offset开始接着消费

意思就是,只要这个消费者组消费过了,不管auto.offset.reset指定成什么值,效果都一样,每次启动都是已有的最新的offset开始接着往后消费

不同的点为:

latest(默认):对于同一个消费者组,若没有提交过offset,则只消费消费者连接topic后,新产生的数据
就是说如果这个topic有历史消息,现在新启动了一个消费者组,且auto.offset.reset=latest,此时已存在的历史消息无法消费到,那保持消费者组运行,如果此时topic有新消息进来了,这时新消息才会被消费到。而一旦有消费,则必然会提交offset
这时候如果该消费者组意外下线了,topic仍然有消息进来,接着该消费者组在后面恢复上线了,它仍然可以从下线时的offset处开始接着消费,此时走的就是共同定义

earliest:对于同一个消费者组,若没有提交过offset,则从头开始消费
就是说如果这个topic有历史消息存在,现在新启动了一个消费者组,且auto.offset.reset=earliest,那将会从头开始消费,这就是与latest不同之处。
一旦该消费者组消费过topic后,此时就有该消费者组的offset了,这种情况下即使指定了auto.offset.reset=earliest,再重新启动该消费者组,效果是与latest一样的,也就是此时走的是共同的定义

none:对于同一个消费者组,若没有提交过offset,会抛异常
一般生产环境基本用不到该参数

触发创建Kafka消费者代码如下

@RestController
@RequestMapping("/kafka")
public class KafkaDemo {

    /**
     * 线程缓存工具
     */
    public static Map<String, Thread> threadHashMap = new ConcurrentHashMap<>();

    /**
     *  Kafka消费者创建消费
     * @param ip kafka连接ip
     * @param topic kafka消费topic
     */
    @GetMapping("/start")
    public void start(@RequestParam("ip") String ip, @RequestParam("topic") String topic) {

        KafkaTest kafkaDemo = new KafkaTest(topic, ip, new TestCallBack() {
            @Override
            public void callBack(String s) {
                System.out.println("Kafka消费到的消息 : " + s);
            }
        });
        threadHashMap.put("10.4.130.71:9092/kafkaDemo", kafkaDemo);
        kafkaDemo.start();
        System.out.println(123);
    }

    /**
     *  Kafka消费者停止
     * @param ip kafka连接ip
     * @param topic kafka消费topic
     */
    @GetMapping("/stop")
    public void stop(@RequestParam("ip") String ip, @RequestParam("topic") String topic) {
        Thread thread = threadHashMap.get(ip + topic);
        KafkaTest.kafka.put(ip + topic, false);
        thread.isInterrupted();
    }

}

 在调用创建Kafka消费者时可以进行回调方式实现,这样就可以在外部进行消费者的消费数据进行后续逻辑实现

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供有关Java实现Kafka消费并回调的帮助。在Java中,您可以使用Kafka的Consumer API来实现消费者逻辑,并使用Kafka的Callback机制来回调处理结果。以下是示例代码: ```java import org.apache.kafka.clients.consumer.*; import org.apache.kafka.common.TopicPartition; import java.util.*; public class MyKafkaConsumer { private static final String TOPIC_NAME = "my-topic"; // Kafka主题名称 private static final String GROUP_ID = "my-group"; // 消费者组ID public static void main(String[] args) { Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); // Kafka集群地址 props.put("group.id", GROUP_ID); props.put("enable.auto.commit", "false"); // 手动提交消费位移 props.put("auto.offset.reset", "earliest"); // 从最早的消息开始消费 props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); // 反序列化器 props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props); // 订阅主题 consumer.subscribe(Collections.singletonList(TOPIC_NAME), new ConsumerRebalanceListener() { @Override public void onPartitionsRevoked(Collection<TopicPartition> partitions) { // 消费者停止消费分区时调用 consumer.commitSync(currentOffsets()); } @Override public void onPartitionsAssigned(Collection<TopicPartition> partitions) { // 消费者开始消费分区时调用 } }); try { while (true) { ConsumerRecords<String, String> records = consumer.poll(1000); // 拉取消息 for (ConsumerRecord<String, String> record : records) { System.out.printf("消费消息: partition = %d, offset = %d, key = %s, value = %s%n", record.partition(), record.offset(), record.key(), record.value()); // TODO: 处理消息逻辑 } consumer.commitAsync(); // 异步提交消费位移 } } finally { consumer.close(); // 关闭消费者 } } // 获取当前消费者消费位移 private static Map<TopicPartition, OffsetAndMetadata> currentOffsets() { Map<TopicPartition, OffsetAndMetadata> currentOffsets = new HashMap<>(); for (TopicPartition partition : consumer.assignment()) { currentOffsets.put(partition, new OffsetAndMetadata(consumer.position(partition))); } return currentOffsets; } } ``` 以上代码实现了一个简单的Kafka消费者,并使用了手动提交消费位移以及异步提交消费位移的方式。同时,代码还实现了ConsumerRebalanceListener接口来监听消费者停止消费分区以及开始消费分区的事件。 希望这个例子能够帮助您理解如何在Java实现Kafka消费并回调。如果您有任何其他问题,请随时与我交流。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值