一. Kafka3.7.X使用文档:
1, kafka的下载地址:
2, 解压缩kafka压缩包:
放在目录下,列如: D:\SoftWare\Kafka
二. kafka的启动流程(Windows):
1, ZooKeeper启动:
- 进入kafka/config目录下,修改zookeeper.properties配置文件:
#修改数据储存位置:
dataDir=D:/SoftWare/Kafka/data/zk
- 打开cmd黑窗口执行zookeeper启动脚本:
zookeeper-server-start.bat ../../config/zookeeper.properties
- 或者使用脚本自行启动dos:
call bin/windows/zookeeper-server-start.bat config/zookeeper.properties
2, Kafka启动:
- 进入kafka/config目录下,修改server.properties配置文件:
log.dirs=D:/kafka/data/kafka
- 使用脚本dos自行启动kafka:
call bin/windows/kafka-server-start.bat config/server.properties
3, 启停顺序:
启动时: 先启动zookeeper再启动kafka;
#==========
关闭时: 先关闭kafka再关闭zookeeper;
4, 查看进程:
- 在kafka的目录下,打开dos窗口:
#使用如下命令即可查看kafka相关进程:
jps
三. Kafka的基础结构:
1, Producer:
- Producer消息生产者: 连接broker,并把消息发送到某一个分区中,如Partition0, Partition1, Partition2。
2, Consumer:
- Consumer消息消费者: 每个消费者都属于某一个Consumer Group(消费者组),一个消费者组内的消费者,
- 只能有一个消费某个分区(Partition)的消息,但不同组的消费者,可以消费同一个分区的消息。
3, Broker:
- 一台Kafka服务就是一个Broker。
4, Partition:
- Partition分区: 每个分区是一个有序的队列,用于存放消息。
5, ZooKeeper:
- 它可以作为配置中心,生产者,消费者,Broker,topic都需要在ZooKeeper上进行注册。
四. 创建一个Topic:
- 在kafka的主目录下,打开dos窗口创建一个Kafka的Topic:
.\bin\windows\kafka-topics.bat --create -bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic FirstTopic
- 参数配置的解释:
-
replication-factor(副本因子):
副本因子是个正整数,表示每个分区的副本数量。
副本因子应该不大于broker的数量,以避免副本在同一台机器上,这可能会导致数据丢失。
设置副本因子为2或3通常是比较常见的,因为它提供了一定程度的容错性。
如果数据对可靠性要求很高,那么需要设置较高的副本因子。
-
partitions(分区):
Kafka topic的分区数量是一个正整数,可以设置为1到2^31-1之间的值。
分区数量应该根据数据吞吐量和容错需求来确定。一个较大的分区数量可以提高并发性,但也会增加管理开销。
通常情况下,分区数量不应该超过集群中broker的数量,因为broker的数量决定了topic的最大并行处理能力。
如果会有大量的数据写入,应该从一开始就规划好足够的分区数量,因为增加分区数量之后再进行扩展可能会比较复杂。
1, 查看Topic:
- 在kafka的主目录下,打开dos窗口查看Topic信息:
.\bin\windows\kafka-topics.bat --describe --topic FirstTopic --bootstrap-server localhost:9092
- 参数信息的解释:
-
partiotionCount: 当前Topic的分区总数。
-
replicationFactor: 当前Topic的副本总数。
-
leader: 代表分区的leader在哪个broker上,0代表Leader在broker.id = 0上。
-
Relicas: 列出所有的副本在哪些broker上,一个leader可以有多个不同的follower,0代表此副本在broker.id = 0上,
-
Isr (In-Sync Replicas): 代表的是一个分区的所有副本中,与leader同步的副本集合。
ISR集合中的副本负责接收和处理来自producer的消息。 当producer发送消息到一个topic的某个分区时,它只会将消息发送到ISR集合中的某个副本(通常是leader副本)。 如果leader副本失败了,Kafka会从ISR集合中选择一个新的leader副本。 ISR的存在确保了如果某个副本失效,数据不会丢失,因为ISR中的副本可以作为新的leader继续提供服务。
- 查看当前所有topic:
.\bin\windows\kafka-topics.bat --list --bootstrap-server localhost:9092
五. kafka的生产和消费:
1, 启动消费者:
- 在kafka的主目录下,打开dos窗口,启动Consumer:
.\bin\windows\kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic FirstTopic
- 查看该Consumer的某个Topic是否有消费消息:
.\bin\windows\kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic FirstTopic --from-beginning
2, 启动生产者:
- 在kafka的主目录下,打开dos窗口,启动Producer:
.\bin\windows\kafka-console-producer.bat --broker-list localhost:9092 --topic FirstTopic
3, 服务的关闭顺序:
生产者和消费者 --> kafka --> zookeeper;
六. SpringBoot整合Kafka:
1. 搭建一个父工程:
- 父工程Pom.xml导入依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>kafkatest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>kafka-consumer</module>
<module>kafka-producer</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
2. 搭建Producer子工程:
- 子工程的pom.xml,继承父工程的依赖:
<parent>
<groupId>org.example</groupId>
<artifactId>kafkatest</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>kafka-producer</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
- 创建SpringBoot启动类:
@SpringBootApplication
@EnableScheduling
public class SpringProducer {
public static void main(String[] args) {
SpringApplication.run(SpringProducer.class, args);
}
}
- 创建application.yml文件:
server:
port: 8090
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
acks: all
retries: 0
- 搭建一个ProducerConfig类:
@Configuration
public class ProducerConfig {
@Value("${spring.kafka.bootstrap-servers}")
private String bootstrapServers;
@Value("${spring.kafka.producer.key-serializer}")
private String keySerializer;
@Value("${spring.kafka.producer.value-serializer}")
private String valueSerializer;
@Bean
public Map<String, Object> getProps() {
HashMap<String, Object> props = new HashMap<>();
props.put("bootstrap.servers", bootstrapServers);
props.put("key.serializer", keySerializer);
props.put("value.serializer", valueSerializer);
return props;
}
@Bean
public ProducerFactory<String, Object> producerFactory() {
return new DefaultKafkaProducerFactory<>(getProps());
}
@Bean
public KafkaTemplate<String, Object> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
}
- 搭建一个Service类,用于写业务代码:
- 这里用于发送十条消息。
@Service("kafkaService")
public class KafkaSendService {
@Resource
private KafkaTemplate<String, Object> kafkaTemplate;
public void send() {
for (int i = 0; i < 10; i++) {
kafkaTemplate.send("FirstTopic", "Hello,Kafka!" + i).addCallback(success -> System.out.println("消息发送成功: " + success), ex -> System.out.println("消息发送失败: " + ex));
}
}
}
- 创建定时任务用于测试:
@Component
public class SendMsg {
@Resource private KafkaSendService kafkaSendService;
@Scheduled(cron = "0/10 * * * * *")//10秒运行一次
public void sendMsg(){
kafkaSendService.send();
}
}
3.搭建Consumer子工程:
- 子工程的pom.xml,继承父工程的依赖:
<parent>
<groupId>org.example</groupId>
<artifactId>kafkatest</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>kafka-consumer</artifactId>
- 创建SpringBoot启动类:
@SpringBootApplication
@EnableScheduling
public class SpringConsumer {
public static void main(String[] args) {
SpringApplication.run(SpringConsumer.class, args);
}
}
- 创建application.yml文件:
server:
port: 8080
spring:
kafka:
bootstrap-servers: localhost:9092
consumer:
group-id: test-group
auto-commit-interval: 1000
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
enable-auto-commit: true
- 搭建一个ConsumerConfig类:
@Configuration
@EnableKafka
public class ConsumerConfig {
@Value("${spring.kafka.bootstrap-servers}")
private String bootstrapServers;
@Value("${spring.kafka.consumer.group-id}")
private String groupId;
@Value("${spring.kafka.consumer.key-deserializer}")
private String keyDeserializer;
@Value("${spring.kafka.consumer.value-deserializer}")
private String valueDeserializer;
@Bean
public Map<String, Object> getProps() {
HashMap<String, Object> props = new HashMap<>();
props.put("bootstrap.servers", bootstrapServers);
props.put("group.id", groupId);
props.put("key.deserializer", keyDeserializer);
props.put("value.deserializer", valueDeserializer);
return props;
}
@Bean
public KafkaConsumer<String, Object> kafkaConsumer() {
return new KafkaConsumer<>(getProps());
}
@Bean
public ConsumerFactory<String, Object> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(getProps());
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, Object> listenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
}
- 搭建一个Service类,用于写业务代码:
- 接受并打印该Topic收到的消息:
@Service("msgService")
public class MsgService {
@Resource
private KafkaConsumer<String, Object> kafkaConsumer;
@KafkaListener(topics = {"FirstTopic"}, groupId = "test-group")//监听该Topic
public void getMsg(string msg) {
//是否需要对数据进行处理...
System.out.println("收到来自test-group的消息: " + msg);
}
}
七. 编程式创建Topic:
1. 创建一个TopicConfig类:
@Configuration
//编程式创建topic
public class KafkaTopicConfig {
private static final String FIRST_TOPIC = "FirstTopic";
@Resource
private ConsumerConfig config;
@Bean
public KafkaAdmin kafkaAdmin() {
return new KafkaAdmin(config.getProps());
}
@Bean
public NewTopic topic() {
return new NewTopic(FIRST_TOPIC, 1, (short) 1);
}
}