springboot集成kafka


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、简介

Kafka is a distributed,partitioned,replicated commit logservice。它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现。kafka对消息保存时根据Topic进行归类,发送消息者成为Producer,消息接受者成为Consumer,此外kafka集群有多个kafka实例组成,每个实例(server)成为broker。无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息。

二、安装步骤

博主最近在学习有关kafka的配置安装以及在spring的集成使用。但网上关于kafka的配置参考资料基本都是于linux下的配置,于是博主在整理了相关windows下kafka的配置记录在博客里。由于是简单配置所以在这里只建了一个topic以及一个producer和两个consumer。

关于kafka具体是什么以及他的设计原理使用场景等等请看上篇博客,转自大佬。传送门:http://www.cnblogs.com/wdfordream/p/7324975.html

在官网上下载 zookeeper和kafka(我下的版本kafka_2.11-0.11.0.0,这个版本中bin目录下有windows目录),注意不要下载源码包(名字中带有src),否则启动的时候会报错。

1、配置好jdk环境

2、zookeeper配置

解压zookeeper到指定目录,找到解压后目录中conf文件夹中zoo_sample - 副本.cfg文件,复制在conf中改名为zoo.cfg。在bin文件夹中打开zkServer.bat启动zookeeper。
在这里插入图片描述
至此,zookeeper启动完成。

3、kafka配置

解压kafka到指定目录。查看kafka根目录中config文件夹下server.properties,确认其中关于zookeeper的连接端口和zookeep中zoo.cfg的端口一致。

3.1、启动kafka

在cmd中进入kafka根目录。输入以下命令:

.\bin\windows\kafka-server-start.bat .\config\server.properties
  在这里插入图片描述
  kafka启动成功

3.2、创建topic

在cmd中进入kafka\bin\windows目录,输入以下命令:

kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 
在这里插入图片描述

创建成功

3.3、创建kafka producer

在cmd中进入kafka\bin\windows目录,输入以下命令:

kafka-console-producer.bat --broker-list localhost:9092 --topic test

注意这里的端口和server.properties的端口号一致。
在这里插入图片描述

3.4创建consumer

在cmd中进入kafka\bin\windows目录,输入以下命令:

kafka-console-consumer.bat --zookeeper localhost:2181 --topic test (旧版本)
  kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning(新版本)
在这里插入图片描述

以同样的方式创建另一个consumer。

4、环境测试

在producer中输入一句话并回车,可以在两个consumer中得到相关信息。

在这里插入图片描述

5、Kafka查看topic、consumer group状态命令

原文链接:https://www.cnblogs.com/AcAc-t/p/kafka_topic_consumer_group_command.html

最近工作中遇到需要使用kafka的场景,测试消费程序启动后,要莫名的过几十秒乃至几分钟才能成功获取到到topic的partition和offset,而后开始消费数据,于是学习了一下查看kafka broker里topic和consumer group状态的相关命令,这里记录一下。

命令参考自《Kafka: The Definitive Guide》 Chapter 9 Administrating Kafka

以下命令中使用的zookeeper配置地址为127.0.0.1:2181,bootstrap–server(即broker)地址为: 127.0.0.1:9292

1,查看kafka topic列表,使用–list参数

bin/kafka-topics.sh --zookeeper 127.0.0.1:2181 --list
__consumer_offsets
lx_test_topic
test
2,查看kafka特定topic的详情,使用–topic与–describe参数

bin/kafka-topics.sh --zookeeper 127.0.0.1:2181 --topic lx_test_topic --describe
Topic:lx_test_topic PartitionCount:1 ReplicationFactor:1 Configs:
Topic: lx_test_topic Partition: 0 Leader: 0 Replicas: 0 Isr: 0
列出了lx_test_topic的parition数量、replica因子以及每个partition的leader、replica信息

3,查看consumer group列表,使用–list参数

查看consumer group列表有新、旧两种命令,分别查看新版(信息保存在broker中)consumer列表和老版(信息保存在zookeeper中)consumer列表,因而需要区分指定bootstrap–server和zookeeper参数:

bin/kafka-consumer-groups.sh --new-consumer --bootstrap-server 127.0.0.1:9292 --list
lx_test
bin/kafka-consumer-groups.sh --zookeeper 127.0.0.1:2181 --list
console-consumer-86845
console-consumer-11967

4,查看特定consumer group 详情,使用–group与–describe参数

同样根据新/旧版本的consumer,分别指定bootstrap-server与zookeeper参数:

bin/kafka-consumer-groups.sh --new-consumer --bootstrap-server 127.0.0.1:9292 --group lx_test --describe
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG OWNER
lx_test lx_test_topic 0 465 465 0 kafka-python-1.3.1_/127.0.0.1
bin/kafka-consumer-groups.sh --zookeeper 127.0.0.1:2181 --group console-consumer-11967 --describe
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG OWNER
Could not fetch offset from zookeeper for group console-consumer-11967 partition [lx_test_topic,0] due to missing offset data in zookeeper.
console-consumer-11967 lx_test_topic 0 unknown 465 unknown console-consumer-11967_aws-lx-1513787888172-d3a91f05-0
其中依次展示group名称、消费的topic名称、partition id、consumer group最后一次提交的offset、最后提交的生产消息offset、消费offset与生产offset之间的差值、当前消费topic-partition的group成员id(不一定包含hostname)

上面示例中console-consumer-11967是为了测试临时起的一个console consumer,缺少在zookeeper中保存的current_offset信息。

5.创建topic命令
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
在这里插入图片描述
6.启动生产者控制台命令
kafka-console-producer.bat --broker-list localhost:9092 --topic test
在这里插入图片描述

7.启动消费者监听控制点命令
kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test在这里插入图片描述

6、其他相关命令

查看已建立的topics:kafka-topics.bat --list --zookeeper localhost:2181

查看每个节点信息 :kafka-topics.bat --describe --zookeeper localhost:2181 --topic my-replicated-topic

7、问题整理

6.1、kafka启动时报异常Caused by:java.lang.OutOfMemoryError:Map failed

在这里博主的办法是将kafka-server-run.bat里的参数set KAFKA_HEAP_OPTS=-Xmx512M -Xms512M改为256M,如果有更好的解决办法谢谢大家能告诉我。

6.2、kafka启动时报异常Caused by: java.nio.file.FileSystemException: \tmp\kafka-logs\topic.alarmMatchFace-0\00000000000000009163.log -> \tmp\kafka-logs\topic.alarmMatchFace-0\00000000000000009163.log.deleted: 另一个程序正在使用此文件,进程无法访问。

主要是因为tmp/kafka-logs文件的日志达到了1G且未被清理。由于这样的错误是在kafka服务关闭后重启kafka服务引起的,博主暂无什么好的解决方法,每次把tmp下的kafka-logs文件夹删除,再启动kafka服务就不会报错了,希望各位大大如果有好的方法能告知我一下,谢谢啦。

6.3、kafka 创建消费者报错 consumer zookeeper is not a recognized option
在做kafka测试的时候,使用命令bin/kafka-console-consumer.sh --zookeeper 192.168.0.140:2181,192.168.0.141:2181 --topic test --from-beginning启动消费者,发现一只报错consumer zookeeper is not a recognized option,搜索了半天,一只没有解决,最后,换了一个低版本的kakfa,发现在启动的时候说使用 --zookeeper是一个过时的方法,此时,才知道原来在最新的版本中,这种启动方式已经被删除了,
最后附上0.90版本之后启动消费者的方法: bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning

8、springboot集成kafka

1.kafka配置类KafkaConfig

package com.xxx;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.*;
import org.springframework.kafka.listener.AbstractMessageListenerContainer;
import org.springframework.kafka.listener.config.ContainerProperties;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableKafka
public class KafkaConfig {

    @Value("${spring.kafka.bootstrap-servers}")
    private String kafkaServers;

    @Value("${spring.kafka.listener.concurrency}")
    private Integer listenerConcurrency;

    @Value("${spring.kafka.consumer.enable-auto-commit}")
    private Boolean consumerEnableAutoCommit;



    @Bean
    public KafkaTemplate<String, Object> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }

    @Bean
    public ProducerFactory<String, Object> producerFactory() {
        return new DefaultKafkaProducerFactory<>(producerConfigs());
    }

    @Bean
    public Map<String, Object> producerConfigs() {
        Map<String, Object> props = new HashMap<>(16);
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServers);
        props.put(ProducerConfig.RETRIES_CONFIG, "3");
        props.put(ProducerConfig.ACKS_CONFIG, "all");
        props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "gzip");
        props.put(ProducerConfig.BATCH_SIZE_CONFIG, 200);
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
                "org.apache.kafka.common.serialization.StringSerializer");
        return props;
    }


    @Bean("myKafkaContainerFactory")
    ConcurrentKafkaListenerContainerFactory<Object, Object> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<Object, Object> factory =
                new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        factory.setConcurrency(listenerConcurrency);
        //factory.getContainerProperties().setAckMode(AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIATE);
        return factory;
    }

    @Bean
    public ConsumerFactory< Object,Object> consumerFactory() {
        return new DefaultKafkaConsumerFactory<>(consumerConfigs());
    }

    @Bean
    public Map<String, Object> consumerConfigs() {
        Map<String, Object> props = new HashMap<>(16);
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServers);
        props.put(ConsumerConfig.GROUP_ID_CONFIG, KafkaConstant.FRONT_TOPIC_GROUP);
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, consumerEnableAutoCommit);
        props.put(ConsumerConfig.CLIENT_ID_CONFIG, "localhost" + "-h5-consumer");
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        return props;
    }
}

2.生产者类KafkaProducer

package com.xxx;
import com.alibaba.fastjson.JSONObject;
import com.xxx.KafkaConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;

/**
 * Kafka生产者
 * @version 1.0 since 2021-01-15
 */
@Component
@Slf4j
public class KafkaProducer {

    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;

    @Value("${topic.name}")
    private String topicName;

    public void send(Object obj) {
        String obj2String = JSONObject.toJSONString(obj);
        log.info("准备发送消息为:{}", obj2String);
        //发送消息
        ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topicName, obj);
        future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
            @Override
            public void onFailure(Throwable throwable) {
                //发送失败的处理
                log.info(KafkaConstant.FRONT_TOPIC_GROUP + " - 生产者 发送消息失败:" + throwable.getMessage());
            }

            @Override
            public void onSuccess(SendResult<String, Object> stringObjectSendResult) {
                //成功的处理
                log.info(KafkaConstant.FRONT_TOPIC_GROUP + " - 生产者 发送消息成功:" + stringObjectSendResult.toString());
            }
        });


    }
}

2.消费者类KafkaConsumer

package com.xxx.consumer;

import com.xxx.KafkaConstant;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * Kafka消费者
 *
 * @author v_honwang
 * @version 1.0 since 2021-01-15
 */
@Component
@Log4j2
public class KafkaConsumer {

    @KafkaListener(topics = {"#{'${topic.name}'.split(',')}"},containerFactory="myKafkaContainerFactory")
    public void topicTest(String record, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
        Optional message = Optional.ofNullable(record);
        if (message.isPresent()) {
            Object msg = message.get();
            log.info("topic_test 消费了: Topic:" + topic + ",Message:" + msg);

        }
    }
}

application.properties注入的配置

#==============kafka相关配置
spring.kafka.bootstrap-servers=localhost:9092
topic.name=test

#spring.kafka.bootstrap-servers=10.241.131.98:8080
spring.kafka.producer.buffer-memory=33554432
spring.kafka.listener.concurrency=3
spring.kafka.consumer.enable-auto-commit=true

#spring.kafka.producer.retries=0
#spring.kafka.producer.batch-size=16384

#spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
#spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
#spring.kafka.producer.acks=1
#spring.kafka.consumer.auto-commit-interval=1S
#spring.kafka.consumer.auto-offset-reset=earliest
#spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
#spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
#spring.kafka.listener.ack-mode=manual_immediate
#spring.kafka.listener.missing-topics-fatal=false

问题总结:
springboot 多topic 动态配置
项目中需要能够动态配置topic进行消费。

1.application.properties中配置topicName=topic1,topic2

2.@KafkaListener(topics = {"#{’${topicName}’.split(’,’)}"})

3.pom文件引入springkafka-1.2.2,不能引入springkafka-1.1.0。

总结

参考https://blog.csdn.net/z69183787/article/details/109321253

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值