前言
kafka是一个分布式消息队列。具有高性能、持久化、多副本备份、横向扩展能力。生产者往队列里写消息,消费者从队列里取消息进行业务逻辑。一般在架构设计中起到解耦、削峰、异步处理的作用。
特性
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作;
- 可扩展性:kafka集群支持热扩展;
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失;
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败);
- 高并发:支持数千个客户端同时读写;
- 支持实时在线处理和离线处理:可以使用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已经讲解完成,如有问题,请随时反馈。