Spring Boot集成kafka(一)

2,326 阅读4分钟

前言

kafka是一个分布式消息队列。具有高性能、持久化、多副本备份、横向扩展能力。生产者往队列里写消息,消费者从队列里取消息进行业务逻辑。一般在架构设计中起到解耦、削峰、异步处理的作用。

特性

  1. 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作;
  2. 可扩展性:kafka集群支持热扩展;
  3. 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失;
  4. 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败);
  5. 高并发:支持数千个客户端同时读写;
  6. 支持实时在线处理和离线处理:可以使用Storm这种实时流处理系统对消息进行实时进行处理,同时还可以使用Hadoop这种批处理系统进行离线处理;

安装kafka

在安装kafka之前,需要先安装zookeeper,关于zookeeper的安装请参考juejin.cn/post/707590…

1.下载安装包

 wget https://mirrors.bfsu.edu.cn/apache/kafka/2.8.0/kafka_2.12-2.8.0.tgz

2.解压安装包

 tar -xzf kafka_2.12-2.8.0.tgz

3.修改基础配置,进入进入 /usr/local/kafka/config目录,打开service.properties

#内网地址
listeners=PLAINTEXT://ip:port

#外网IP地址,建议配置为外网域名
advertised.listeners=PLAINTEXT://ip:port

#"PLAINTEXT"表示协议,可选的值有PLAINTEXT和SASL,hostname可以指定IP地址,也可以用"0.0.0.0"表示对所有的网络接口有效,但是会存在安全性问题。

# 默认处理网络请求的线程个数 3个
num.network.threads=3

# 执行磁盘IO操作的默认线程个数 8
num.io.threads=8

# socket服务使用的进行发送数据的缓冲区大小,默认100kb
socket.send.buffer.bytes=102400

# socket服务使用的进行接受数据的缓冲区大小,默认100kb
socket.receive.buffer.bytes=102400

# socket服务所能够接受的最大的请求量,防止出现OOM(Out of memory)内存溢出,默认值为:100m
socket.request.max.bytes=104857600

#日志路径
log.dirs=/log/kafka/logs

#每一个topic所对应的log的partition分区数目,默认1个。更多的partition数目会提高消费
#并行度,但是也会导致在kafka集群中有更多的文件进行传输
num.partitions=1

# 每一个数据目录用于在启动kafka时恢复数据和在关闭时刷新数据的线程个数。如果kafka数据存储在磁盘阵列中
# 建议此值可以调整更大。
num.recovery.threads.per.data.dir=1

#zookeeper配置,如果配置多个,分开。eg:"127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
zookeeper.connect=localhost:2181

# Timeout in ms for connecting to zookeeper
zookeeper.connection.timeout.ms=6000

4.新增启动和关闭kafka脚本。

kafka启动脚本内容如下:

#!/bin/bash
#启动zookeeper
/usr/local/kafka/bin/zookeeper-server-start.sh /usr/local/kafka/config/zookeeper.properties &
sleep 3  #默默等3秒后执行 
#启动kafka
/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties &

kakfa的关闭脚本内容如下:

#!/bin/bash
#停止kafka
 /usr/local/kafka/bin/kafka-server-stop.sh 

sleep 3  #默默等3秒后执行 
#停止zookeeper
 /usr/local/kafka/bin/zookeeper-server-stop.sh 

执行kafkastart.sh 脚本,启动kafka。

测试

cd /usr/local/kafka/bin 目录执行如下命令:

 新增topic

./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test

生成者
./kafka-console-producer.sh --broker-list localhost:9092 --topic test  --producer.config  ../config/producer.properties

消费者
./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test  --consumer.config   ../config/consumer.properties

可以通过生产者发送消息,消费者接收对应的消息,则表示kafka安装成功,能够正常通信。

Spring Boot集成

1.引入jar包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
    <dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.62</version>
		</dependency>

2.application.yml配置kafka信息

 spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      # 指定 group_id
      group-id: group_id
      auto-offset-reset: earliest
      # 指定消息key和消息体的编解码方式
   key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
   value-deserializer:org.apache.kafka.common.serialization.StringDeserializer   
   producer:
      # 指定消息key和消息体的编解码方式
      key-deserializer: org.apache.kafka.common.serialization.StringSerializer
      value-deserializer: org.apache.kafka.common.serialization.StringSerializer

3.编写生产者

@RestController
@RequestMapping("/kafka")
public class KafkaProducer
{
    private static final Logger logger =    LoggerFactory.getLogger(KafkaProducer.class);
    
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    
    @RequestMapping("/send")
     public void send(){
         Message message = new Message();
         message.setId(UUID.randomUUID().toString());
         message.setSendTime(new Date());
         message.setContent("这是一个测试消息");
         logger.info("--------------- message = {}", JSON.toJSONString(message));
         //topic为test
         kafkaTemplate.send("test", JSON.toJSONString(message));
     }
}

4.编写消费者

 #topics为创建的topic的名称
 @KafkaListener(topics = {"test"})
    public void listen(ConsumerRecord<?, ?> record) 
    {
        Optional<?> kafkaMessage = Optional.ofNullable(record.value());
        if (kafkaMessage.isPresent()) 
        {
            Object message = kafkaMessage.get();
            logger.info("====>接收到kafka消息: topic = {}, offset = {} \n", record.topic(), record.offset());
            logger.info(" kafka message:{}" + message);
        }
    }

运行程序,可以看到如下信息,表示kafka发送成功:

2022-03-24 08:59:35.223 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO  [] c.s.f.message.producer.KafkaProducer - ====>接收到kafka消息: topic = test, offset = 0 

2022-03-24 08:59:35.224 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO  [] c.s.f.message.producer.KafkaProducer -  kafka message:{}{"content":"这是一个测试消息","id":"b95d79c2-1da9-47ef-b7cd-1b92419fe135","sendTime":1648083565563}

Spring Boot 集成kafka已经讲解完成,如有问题,请随时反馈。