• Kafka——Spring集成Kafka


    准备工作

    • 安装kafka+zookeeper环境
    • 利用命令创建好topic
    • Pom文件,引入spring-kafka jar包这里需要注意2个地方:

    1. kafka-clients 包版本与服务器端kafka-clients版本保持一致(查看服务器kafka版本方法 在kafka安装目录下libs 中查找kafka-clients开头的jar文件)
    2. 引入的spring-kafka 版本在2.0或者2.X 时Spring版本在5.0才能支持
      ..........
    <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.1.8.RELEASE</version> </dependency>
      ..........

    参考官网 http://kafka.apache.org/documentation/ 

    XML配置方式

    • 生产者

    配置:

     <?xml version="1.0" encoding="UTF-8"?>
     <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans  
              http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
              http://www.springframework.org/schema/context  
              http://www.springframework.org/schema/context/spring-context.xsd">
         <context:property-placeholder location="classpath*:config/application.properties" />
         <!-- 定义producer的参数 -->
         <bean id="producerProperties" class="java.util.HashMap">
             <constructor-arg>
                 <map>
                     <entry key="bootstrap.servers" value="${bootstrap.servers}" />
                     <entry key="group.id" value="${group.id}" />
                     <entry key="retries" value="${retries}" />
                     <entry key="batch.size" value="${batch.size}" />
                     <entry key="linger.ms" value="${linger.ms}" />
                     <entry key="buffer.memory" value="${buffer.memory}" />            
                     <entry key="acks" value="${acks}" />              
                     <entry key="key.serializer" value="org.apache.kafka.common.serialization.StringSerializer" />
                     <entry key="value.serializer" value="org.apache.kafka.common.serialization.StringSerializer" />
                 </map>
             </constructor-arg>
         </bean>
     
         <!-- 创建kafkatemplate需要使用的producerfactory bean -->
         <bean id="producerFactory"
             class="org.springframework.kafka.core.DefaultKafkaProducerFactory">
             <constructor-arg>
                 <ref bean="producerProperties" />
             </constructor-arg>
         </bean>
     
         <!-- 创建kafkatemplate bean,使用的时候,只需要注入这个bean,即可使用template的send消息方法 -->
         <bean id="kafkaTemplate" class="org.springframework.kafka.core.KafkaTemplate">
             <constructor-arg ref="producerFactory" />
             <constructor-arg name="autoFlush" value="true" />
             <property name="defaultTopic" value="default" />
         </bean>
     </beans>

    如上图,xml主要配置了KafkaTemplate的构造参数producerFactory和autoFlush,对应了一个KafkaTemplate源码中的2参构造函数。

    1. producerProperties:设置生产者工厂需要的配置
    2. producerFactory:定义了生产者工厂构造方法
    3. kafkaTemplate:定义了使用producerFactory和是否自动刷新,2个参数来构造kafka生产者模板类

    发送消息:

    ListenableFuture<SendResult<String, String>> listenableFuture = kafkaTemplate.send("topic", "partition","key","data");
    //发送成功回调 SuccessCallback<SendResult<String, String>> successCallback = new SuccessCallback<SendResult<String, String>>() { @Override public void onSuccess(SendResult<String, String> result) { //成功业务逻辑 } }
    //发送失败回调 FailureCallback failureCallback = new FailureCallback() { @Override public void onFailure(Throwable ex) { //失败业务逻辑 } } listenableFuture.addCallback(successCallback, failureCallback);
    • 消费者

    配置:

     <!-- 1.定义consumer的参数 -->
         <bean id="consumerProperties" class="java.util.HashMap">
             <constructor-arg>
                 <map>
                     <entry key="bootstrap.servers" value="${bootstrap.servers}" />
                     <entry key="group.id" value="${group.id}" />
                     <entry key="enable.auto.commit" value="${enable.auto.commit}" />
                     <entry key="session.timeout.ms" value="${session.timeout.ms}" />
                     <entry key="key.deserializer"
                         value="org.apache.kafka.common.serialization.StringDeserializer" />
                     <entry key="value.deserializer"
                         value="org.apache.kafka.common.serialization.StringDeserializer" />
                 </map>
             </constructor-arg>
         </bean>
     
         <!-- 2.创建consumerFactory bean -->
         <bean id="consumerFactory"
             class="org.springframework.kafka.core.DefaultKafkaConsumerFactory" >
             <constructor-arg>
                 <ref bean="consumerProperties" />
             </constructor-arg>
         </bean>
     
         <!-- 3.定义消费实现类 -->
         <bean id="kafkaConsumerService" class="xxx.service.impl.KafkaConsumerSerivceImpl" />
     
         <!-- 4.消费者容器配置信息 -->
         <bean id="containerProperties" class="org.springframework.kafka.listener.config.ContainerProperties">
             <!-- topic -->
             <constructor-arg name="topics">
                 <list>
                     <value>${kafka.consumer.topic.credit.for.lease}</value>
                     <value>${loan.application.feedback.topic}</value>
                 </list>
             </constructor-arg>
             <property name="messageListener" ref="kafkaConsumerService" />
         </bean>
         <!-- 5.消费者并发消息监听容器,执行doStart()方法 -->
         <bean id="messageListenerContainer" class="org.springframework.kafka.listener.ConcurrentMessageListenerContainer" init-method="doStart" >
             <constructor-arg ref="consumerFactory" />
             <constructor-arg ref="containerProperties" />
             <property name="concurrency" value="${concurrency}" />
         </bean>
    1. consumerProperties-》consumerFactory 载入配置构造消费者工厂
    2. messageListener-》containerProperties 载入容器配置(topics)
    3. consumerFactory+containerProperties-》messageListenerContainer 容器配置(topics)+消息监听器,构造一个并发消息监听容器,并执行初始化方法doStart
    4. 需要注意. KafkaConsumerSerivceImpl 此类 需要实现 MessageListener 接口

    消费消息:

    方案1:直接实现MessageListener接口,复写onMessage方法,实现自定义消费业务逻辑。

     public class KafkaConsumerSerivceImpl implements MessageListener<String, String> {
         @Override
         public void onMessage(ConsumerRecord<String, String> data) {
             //根据不同主题,消费
             if("主题1".equals(data.topic())){
                 //逻辑1
             }else if("主题2".equals(data.topic())){
                 //逻辑2
             }
         }
     }

    方案2:使用@KafkaListener注解,并设置topic,支持SPEL表达式。这样方便拆分多个不同topic处理不同业务逻辑。(特别是有自己的事务的时候,尤其方便)

    import org.springframework.kafka.annotation.KafkaListener;
    
    public class KafkaConsumerSerivceImpl {
        @KafkaListener(topics = "${templar.aggrement.agreementWithhold.topic}")
        void templarAgreementNoticewithhold(ConsumerRecord<String, String> data){
           //消费业务逻辑
        }
    }

    Java注解方式

    • 生产者

    配置:

     /**
      * @description kafka 生产者配置
      */
     @Configuration
     @EnableKafka
     public class KafkaProducerConfig {
         public KafkaProducerConfig(){
             System.out.println("kafka生产者配置");
         }
    @Bean public ProducerFactory<Integer, String> producerFactory() { return new DefaultKafkaProducerFactory(producerProperties()); } @Bean public Map<String, Object> producerProperties() { Map<String, Object> props = new HashMap<String, Object>(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, PropertiesUtil.getInstance().getString("kafka.producer.bootstrap.servers")); props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, PropertiesUtil.getInstance().getString("kafka.producer.key.serializer")); props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,PropertiesUtil.getInstance().getString("kafka.producer.value.serializer")); props.put(ProducerConfig.RETRIES_CONFIG,PropertiesUtil.getInstance().getInt("kafka.producer.retries")); props.put(ProducerConfig.BATCH_SIZE_CONFIG,PropertiesUtil.getInstance().getInt("kafka.producer.batch.size",1048576)); props.put(ProducerConfig.LINGER_MS_CONFIG,PropertiesUtil.getInstance().getInt("kafka.producer.linger.ms")); props.put(ProducerConfig.BUFFER_MEMORY_CONFIG,PropertiesUtil.getInstance().getLong("kafka.producer.buffer.memory",33554432L)); props.put(ProducerConfig.ACKS_CONFIG,PropertiesUtil.getInstance().getString("kafka.producer.acks","all")); return props; } @Bean public KafkaTemplate<Integer, String> kafkaTemplate() { KafkaTemplate kafkaTemplate = new KafkaTemplate<Integer, String>(producerFactory(),true); kafkaTemplate.setDefaultTopic(PropertiesUtil.getInstance().getString("kafka.producer.defaultTopic","default")); return kafkaTemplate; } }

    发送消息:

      跟xml配置一样。

    • 消费者

    配置:

     /**
      * @description kafka 消费者配置
      */
     @Configuration
     @EnableKafka
     public class KafkaConsumerConfig {
         public KafkaConsumerConfig(){
             System.out.println("kafka消费者配置加载...");
         }
    @Bean KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<Integer, String>> kafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory<Integer, String> factory = new ConcurrentKafkaListenerContainerFactory(); factory.setConsumerFactory(consumerFactory()); factory.setConcurrency(3); factory.getContainerProperties().setPollTimeout(3000); return factory; } @Bean public ConsumerFactory<Integer, String> consumerFactory() { return new DefaultKafkaConsumerFactory(consumerProperties()); } @Bean public Map<String, Object> consumerProperties() { Map<String, Object> props= new HashMap<String, Object>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.bootstrap.servers")); props.put(ConsumerConfig.GROUP_ID_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.group.id")); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.enable.auto.commit")); props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.auto.commit.interval.ms")); props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.session.timeout.ms")); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.key.deserializer")); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, PropertiesUtil.getInstance().getString("kafka.consumer.value.deserializer")); return props; } @Bean public KafkaConsumerListener kafkaConsumerListener(){ return new KafkaConsumerListener(); } }

    消费消息:

      跟xml配置一样。

    引用:

    https://www.cnblogs.com/hsc13-lxy14/p/9211224.html

    https://docs.spring.io/spring-kafka/reference/htmlsingle/

  • 相关阅读:
    java抽象类
    java不支持多继承
    logback颜色
    @ConfigurationProperties、@Value、@PropertySource
    redis命令
    mac下安装rabbitmq
    mac下安装jmeter
    python TypeError: 'int' object is not callable 问题解决
    白炽灯串联发光问题_高中知识(原创)
    python 离散序列 样本数伸缩(原创)
  • 原文地址:https://www.cnblogs.com/caoweixiong/p/12987997.html
Copyright © 2020-2023  润新知