springboot 集成 vertx-kafka-client

爲什麼嘗試做這個集成

vertx是一套封裝了netty的異步事件驅動的框架,netty採用的線程模型可以高效處理某些情況下的網絡通訊,然而這套框架需要程序員使用函數編程的方式,不是傳統的方式。本項目主要是爲了構建一個框架。熟悉springboot編程的程序員只需要通過註解或者接口編程的式就可以使用到 vertx-kafka-client。

項目依賴

集成demo採用的依賴如下,主要是spring-boot-starter-web和vertx-kafka-client。

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.vertx/vertx-kafka-client -->
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-kafka-client</artifactId>
            <version>4.0.0</version>
        </dependency>

初始化生產者和消費者Bean

初始化生產者

初始化生產者的邏輯很簡單,通過ApplicationContext取出所有的Consumer類,再通過反射取到消費者上的註解 MessageHandler所標註的信息(包括topic,msgType等)。在config類中,註冊了消費者的事件,並進行topic監聽。代碼如下:

@Bean
    public List<KafkaConsumer> kafkaConsumers(){
   
   
// use consumer for interacting with Apache Kafka
        List<KafkaConsumer> kafkaConsumers = new ArrayList<>();
        Map<String, IKafkaHandler> consumerHandlers = this.context.getBeansOfType(IKafkaHandler.class);
        for(String kafkaHandlerBean : consumerHandlers.keySet()){
   
   


            //通過反射獲取MessageHandler裏的元信息

            try {
   
   
                IKafkaHandler handler = consumerHandlers.get(kafkaHandlerBean);
                Class clazz = handler.getClass();
                Method handleMethod = clazz.getDeclaredMethod("handle",Object.class);
                MessageHandler anno = handleMethod.getAnnotation(MessageHandler.class);
                String consumerGroup = anno.consumerGroup();
                Class msgType = anno.msgType();
                Map<String, String> config = new HashMap<>();
                config.put("bootstrap.servers", "localhost:9092");
                config.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
                config.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
                if(Strings.isNotBlank(consumerGroup)) {
   
   
                    config.put("group.id", consumerGroup);
                }
                config.put("auto.offset.reset", "earliest");
                config.put("enable.auto.commit", "false");
                KafkaConsumer<String,String> consumer = KafkaConsumer.create(vertx, config);

                String topic = anno.topic();
                consumer.handler(message->{
   
   
                    String value = message.record().value();
                    String key = message.record().key();
                    try {
   
   
                        if (msgType.getSimpleName().equals("String")) {
   
   
                            handler.handle(value);
                        } else {
   
   
                            Object var1 = JSON.parseObject(value, msgType);
                            handler.handle(var1);
                        }
                    } catch (Exception e){
   
   
                        logger.info("consume error,msg = {}",value);
                    }
                });
                consumer.exceptionHandler(error->logger.info("consumer出錯{}",error.toString()));
                consumer.subscribe(topic);
                kafkaConsumers.add(consumer);
            } catch (Exception e) {
   
   
                logger.error("error",e);
            }

        }
        return kafkaConsumers;
    }
初始化生產者

生產者的初始化很簡單,直接初始化一個Bean即可。代碼如下:

    @Bean
    public KafkaProducer kafkaProducer(){
   
   
        Map<String, String> config = new HashMap<>();
        config.put("bootstrap.servers", "localhost:9092");
        config.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        config.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        config.put("acks", "1");

// use producer for interacting with Apache Kafka
        KafkaProducer<String, String> producer = KafkaProducer.create(vertx, config);
        return producer;
    }

如何使用消費者

用戶可以通過接口編程的方式的實現來進行 consumer 的使用。繼承如下接口即可,使用 MessageHanlder 表明其 topic, 示例說明:

public class Topic1Handler implements IKafkaHandler<Message> {
   
   

    private static final Logger logger = LoggerFactory.getLogger(Topic1Handler.class);

    /**
     * msgType 需要和 handle裏的參數類型相同
     * @param message
     */
    @MessageHandler(topic = "topic1",msgType = Message.class)
    @Override
    public void handle(Message message) {
   
   
        logger.info("topic1 收到消息:{}",message);
    }
}

如何使用生產者

通過注入producer即可實現一個默認配置的KafkaProducer,進行消息生產的代碼。

@Autowired
KafkaProducer producer;

以上便是大概的代碼,在我的git上有完整的demo,大家可以看看。
https://github.com/chifanchen/intergrate-springboot-with-vertx-kafka-client

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章