Spring-ReactiveKafkaConsumer(反应式消费kafka消息)

1.引入相应的kafka架包

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
    </parent>
            <!-- kafka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-kafka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor.kafka</groupId>
            <artifactId>reactor-kafka</artifactId>
            <version>1.3.11</version>
        </dependency>

关键架包reactor-kafka

2.创建监听监听Template

package com.kittlen.cloud.reactivekafka.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.core.reactive.ReactiveKafkaConsumerTemplate;
import org.springframework.stereotype.Component;
import reactor.kafka.receiver.ReceiverOptions;

import java.util.Collections;

/**
 * @author kittlen
 * @version 1.0
 * @date 2022/38/04 10:38
 */
@Component
public class ReactiveConsumerConfig {

    @Bean
    public ReceiverOptions<String, String> kafkaReceiverOptions(@Value(value = "${kafka.consumer.topic}") String topic, KafkaProperties kafkaProperties) {
        ReceiverOptions<String, String> basicReceiverOptions = ReceiverOptions.create(kafkaProperties.buildConsumerProperties());
        return basicReceiverOptions.subscription(Collections.singletonList(topic));
    }

    @Bean
    public ReactiveKafkaConsumerTemplate<String, String> reactiveKafkaConsumerTemplate(ReceiverOptions<String, String> kafkaReceiverOptions) {
        return new ReactiveKafkaConsumerTemplate<>(kafkaReceiverOptions);
    }
}

3.根据Template创建对应的实际监听业务

package com.kittlen.cloud.reactivekafka.consumers;

import com.alibaba.fastjson.JSON;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.kafka.core.reactive.ReactiveKafkaConsumerTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.kafka.receiver.ReceiverRecord;

/**
 * @author kittlen
 * @version 1.0
 * @date 2022/40/04 10:40
 */
@Service
public class ReactiveConsumerService implements CommandLineRunner {

    protected Log log = LogFactory.getLog(ReactiveConsumerService.class);

    @Autowired
    ReactiveKafkaConsumerTemplate<String, String> requestMsgReactiveKafkaConsumerTemplate;

    private Flux<Mono<Boolean>> dgkConsummer() {
        Flux<Mono<Boolean>> monoFlux = requestMsgReactiveKafkaConsumerTemplate
                .receiveAutoAck()
                .map(cr -> handler(cr))
                .doOnError(throwable -> log.error("something bad happened while consuming : {}", throwable.getMessage()));
        return monoFlux;
    }

    //返回类型根据实际需求自己进行调整
    //在该方法里面如果直接抛出异常,会直接导致停止对该topic的监听
    protected Mono<Boolean> handler(ConsumerRecord<String, String> consumerRecord) {
        try{
             /*
            * 对监听到的数据的处理逻辑 
            * */
            return Mono.just(true);
        }catch (Exception e) {
            return Mono.error(e);
        }
    }

    @Override
    public void run(String... args) {
        dgkConsummer().subscribe(m -> m.subscribe());
    }
}

4.监听多topic

使用同一个ReactiveKafkaConsumerTemplate

创建kafkaReceiverOptions时订阅多个topic

 @Bean
    public ReceiverOptions<String, String> kafkaReceiverOptions(KafkaProperties kafkaProperties) {
        ReceiverOptions<String, String> basicReceiverOptions = ReceiverOptions.create(kafkaProperties.buildConsumerProperties());
        return basicReceiverOptions.subscription(Stream.of("topic1", "topic2").collect(Collectors.toList()));
    }

处理消息时根据topic进行判断

  protected Mono<Boolean> handler(ConsumerRecord<String, String> consumerRecord) {
        try{
            if(consumerRecord.topic().equals("topic1")){
             //***
             }
             /*
            * 对监听到的数据的处理逻辑 
            * */
            return Mono.just(true);
        }catch (Exception e) {
            return Mono.error(e);
        }
    }

定义多个监听template,再根据template创建对应的实际监听业务


    @Bean
    public ReceiverOptions<String, String> kafkaReceiverOptions1(KafkaProperties kafkaProperties) {
        ReceiverOptions<String, String> basicReceiverOptions = ReceiverOptions.create(kafkaProperties.buildConsumerProperties());
        return basicReceiverOptions.subscription(Collections.singletonList("topic1"));
    }

    @Bean
    public ReactiveKafkaConsumerTemplate<String, String> reactiveKafkaConsumerTemplate1(ReceiverOptions<String, String> kafkaReceiverOptions1) {
        return new ReactiveKafkaConsumerTemplate<>(kafkaReceiverOptions1);
    }
    @Bean
    public ReceiverOptions<String, String> kafkaReceiverOptions2(KafkaProperties kafkaProperties) {
        ReceiverOptions<String, String> basicReceiverOptions = ReceiverOptions.create(kafkaProperties.buildConsumerProperties());
        return basicReceiverOptions.subscription(Collections.singletonList("topic2"));
    }

    @Bean
    public ReactiveKafkaConsumerTemplate<String, String> reactiveKafkaConsumerTemplate2(ReceiverOptions<String, String> kafkaReceiverOptions2) {
        return new ReactiveKafkaConsumerTemplate<>(kafkaReceiverOptions2);
    }


    @Resource(name = "reactiveKafkaConsumerTemplate1")
    ReactiveKafkaConsumerTemplate<String, String> requestMsgReactiveKafkaConsumerTemplate1;
    
    @Resource(name = "reactiveKafkaConsumerTemplate2")
    ReactiveKafkaConsumerTemplate<String, String> requestMsgReactiveKafkaConsumerTemplate2;

     private Flux<Mono<Boolean>> dgkConsummer1() {
        Flux<Mono<Boolean>> monoFlux = requestMsgReactiveKafkaConsumerTemplate1
                .receiveAutoAck()
                .map(cr -> handler1(cr))
                .doOnError(throwable -> log.error("something bad happened while consuming : {}", throwable.getMessage()));
        return monoFlux;
    }

    //返回类型根据实际需求自己进行调整
    protected Mono<Boolean> handler1(ConsumerRecord<String, String> consumerRecord) {
        try{
             /*
            * 对监听到的数据的处理逻辑 
            * */
            return Mono.just(true);
        }catch (Exception e) {
            return Mono.error(e);
        }
    }
     private Flux<Mono<Boolean>> dgkConsummer2() {
        Flux<Mono<Boolean>> monoFlux = requestMsgReactiveKafkaConsumerTemplate2
                .receiveAutoAck()
                .map(cr -> handler2(cr))
                .doOnError(throwable -> log.error("something bad happened while consuming : {}", throwable.getMessage()));
        return monoFlux;
    }

    //返回类型根据实际需求自己进行调整
    protected Mono<Boolean> handler2(ConsumerRecord<String, String> consumerRecord) {
        try{
             /*
            * 对监听到的数据的处理逻辑 
            * */
            return Mono.just(true);
        }catch (Exception e) {
            return Mono.error(e);
        }
    }

    @Override
    public void run(String... args) {
        dgkConsummer().subscribe(m -> m.subscribe());
        dgkConsummer2().subscribe(m -> m.subscribe());
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值