kafka集群搭建-使用zookeeper

1.环境准备:

使用如下3台主机搭建zookeeper集群,由于默认的9092客户端连接端口不在本次使用的云服务器开放端口范围内,故端口改为了8093。

172.2.1.69:8093

172.2.1.70:8093

172.2.1.71:8093

2.下载地址

去官网下载,或者使用如下仓库地址下载,本次使用的时kafka_2.13-3.6.1.tgz ,即3.6.1版本,前面的2.13是scala版本,该版本是较新的版本,可以使用zookeeper,也可以不使用zookeeper搭建集群,本次记录使用了zk,zk集群的部署可以参考上一篇记录。

bash 复制代码
# 软件包下载地址,可以切到/kafka/路径,选择自己需要的版本
https://archive.apache.org/dist/kafka/3.6.1/kafka_2.13-3.6.1.tgz

3.软件包下载解压

在上面3台服务器上分别执行wget下载,或者本地下载后上传,本次使用的环境为堡垒机接入,如果使用的是宿主机账密登陆,可以下载配置一台,其余使用SCP命令拷贝过去即可。

bash 复制代码
cd  /usr/local/

wget https://archive.apache.org/dist/kafka/3.6.1/kafka_2.13-3.6.1.tgz

tar -zxvf kafka_2.13-3.6.1.tgz

mv kafka_2.13-3.6.1 kafka

4.修改配置

需要修改logs路径的话,可以在/kafka路径下新建logs路径,并配置到server.properties中,这里使用默认的/tmp/kafka-logs路径。

bash 复制代码
cd kafka
vim conf/server.properties

修改内容如下,

bash 复制代码
# 每个节点唯一的id,这里.69、.70、.71服务器分别设置为了1、2、3
broker.id=1

# 默认为9092,云服务器开放端口问题,改为了8093
port=8093

# 上一篇记录博客搭建的zk集群地址
zookeeper.connect=172.2.1.69:8092,172.2.1.70:8092,172.2.1.71:8092

# 配置监听访问、绑定地址,这里都是PLAINTEXT协议,不需要认证(相当于内网访问)
listeners=PLAINTEXT://0.0.0.0:8093                                                                                                 
advertised.listeners=PLAINTEXT://172.2.1.71:8093

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

5.启动kafka集群

分别在每个节点的bin路径下执行启动脚本

bash 复制代码
# 在3个节点分别执行如下命令,-daemon表示后台启动,不带该参数前台启动
./bin/kafka-server-start.sh -daemon config/server.properties

使用jps命令,或者去kafka启动日志,查看kafka是否启动成功。

6.创建topic`

bash 复制代码
# 创建topic,在任一节点执行都可以。
 ./bin/kafka-topics.sh --bootstrap-server=172.2.1.69:8093,172.2.1.70:8093,172.2.1.71:8093 --create --topic topic-demo --partitions=3 --replication-factor=3
bash 复制代码
# 查看topic是否创建成功,在任一节点执行
./bin/kafka-topics.sh --bootstrap-server=172.2.1.69:8093,172.2.1.70:8093,172.2.1.71:8093 --topic topic-demo --list

7.模拟生产消费消息

需要注意的是网上搜到的一些老的博客kafka命令在高版本中是不再支持 的,如:

sh ./bin/kafka-topics.sh --zookeeper=zk集群地址,可能出现命令无法识别:zookeeper is not a recognized option

需要替换为:sh ./bin/kafka-topics.sh --bootstrap-server=kafka集群地址,注意--bootstrap-server后面跟的是kafka集群地址,不是zookeeper地址。

bash 复制代码
# 在2个节点启动消费者模拟客户端接收消息,在第3个节点启动生产者模拟客户端发送消息
./bin/kafka-console-consumer.sh --bootstrap-server=172.2.1.69:8093,172.2.1.70:8093,172.2.1.71:8093 --topic topic-demo
bash 复制代码
# 在第3个节点启动生产者客户端模拟发送消息:hello
./bin/kafka-console-producer.sh --bootstrap-server=172.2.1.69:8093,172.2.1.70:8093,172.2.1.71:8093 --topic topic-demo

生产者客户端发送hello

此时可以看到2个消费者模拟客户端都受到了消息:hello

8.集成springboot

坐标如下:

bash 复制代码
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

kafka配置类:

bash 复制代码
package com.example.kafka.kafka;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
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.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;

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

@Configuration
@EnableKafka
//@RefreshScope
public class KafkaConfig {

    @Value("${xxxx:172.2.1.69:8093,172.2.1.70:8093,172.2.1.71:8093}")
    private String kafkaServers;
    
    public Map<String, Object> producerConfigs() {
        Map<String, Object> props = new HashMap<>();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServers);
        props.put(ProducerConfig.RETRIES_CONFIG, 0);
        props.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
        props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
        props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        return props;
    }

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

    public Map<String, Object> consumerConfigs() {
        Map<String, Object> props = new HashMap<>();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServers);
        //props.put(ConsumerConfig.GROUP_ID_CONFIG, "0");
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 100);
        props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "20000");
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        return props;
    }

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

    @Bean
    ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> factory =
                new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        return factory;
    }

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

消费者客户端:

bash 复制代码
    @KafkaListener(
            topics = {"topic-demo"},
            groupId = "test1",
            properties = {"auto-offset-reset:latest", "enable.auto.commit:true"}
    )
    public void listen(ConsumerRecord<String, String> consumerRecord) {
        log.info("consumer Received: " + consumerRecord);
    }

生产者发送消息:

bash 复制代码
@RestController
@RequiredArgsConstructor
@RequestMapping("producer")
public class ProducerController {

    private final KafkaTemplate<String, String> kafkaTemplate;

    @PostMapping(path = "/sendCommonMsg")
    public String sendCommonMsg(String topic, String msg) {
        ListenableFuture<SendResult<String, String>> hello_kafka = this.kafkaTemplate.send(topic, "hello kafka");
        SendResult<String, String> sendResult = hello_kafka.completable().join();
        System.out.println(sendResult);
        return "send topic: " + topic + ", msg: " + msg;
    }
}

发送测试:

消费者可以接收到消息:

bash 复制代码
consumer Received: ConsumerRecord(topic = topic-demo, partition = 0, leaderEpoch = 0, offset = 2, CreateTime = 1721720091071, serialized key size = -1, serialized value size = 5, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = hello kafka)

9.IDEA客户端工具

可以使用kafkalytic工具本地开发环境可视化操作kafka服务器,如查看topic,创建topic

相关推荐
程序员的世界你不懂6 小时前
Kafka 推送消息,移动端自动化测试,数据驱动测试
分布式·kafka·linq
计算机软件程序设计16 小时前
Windows下安装kafka
windows·分布式·kafka
java技术小馆16 小时前
Kafka 消息传递模型
分布式·kafka
HBryce2418 小时前
Kafka&&RocketMQ
分布式·kafka·rocketmq
一个儒雅随和的男子21 小时前
kafka消息中间件的rebalance机制
分布式·kafka
小技工丨21 小时前
Flink SQL 读取 Kafka 数据到 Mysql 实战
sql·flink·kafka
BAStriver1 天前
关于kafka常见的问题小结
分布式·kafka
HappyChan1 天前
kakfa生产者消费者实践
云原生·kafka·go
auspicious航2 天前
Linux系统上安装kafka
linux·运维·kafka
fxrz122 天前
探讨消息队列系统:AWS SQS vs. Apache Kafka
kafka·apache·aws