【Kafka】Kafka入門手記

1. 前言

本文爲 Kafka 入門筆記,主要包括 Kafka 單節點部署、生產消費消息,以及新手踩坑記錄。

Kafka 作爲大數據必備組件、消息中間件必學的 Apache 頂級開源項目,服務穩定、高吞吐的流數據處理平臺。具體介紹可查看文末參考文檔。

目前 CSDN 暫不支持 markdown 收縮語句塊,對於文章展示方面略有問題

1.1. 可查看美觀版本

文檔:Kafka 入門手記.md
鏈接:http://note.youdao.com/noteshare?id=d1c65daf3c137f29a860b5efd5dff944&sub=F4E6A5E5FB3946499E7C4C3E6022E1DC

2. Kafka單節點部署

2.1. 下載

http://kafka.apache.org

選擇合適版本即可,這裏選擇最新版本。Linux 環境。

2.2. 解壓

Kafka 安裝包 後綴爲 .tgz , 解壓即可。

tar -zxvf kafka_package.tgz

其中,kafka_package.tgz 是 Kafka 安裝包名稱。

2.2.1. zookeeper 安裝

Kafka 依賴於 zookeeper(ZK) 支持,本文直接採用 Kafka 安裝包自帶的 zookeeper。

也可以單獨部署 zookeeper,使用方式一樣。對於 生產環境,建議單獨搭建 zookeeper。

2.3. 配置

2.3.1. zookeeper

進入 Kafka 解壓包根目錄,config 文件夾下的即爲 Kafka 提供的默認配置文件。

此處我們修改下 zookeeper.propertieshost 信息。此處修改 host 配置,主要是爲了避免在使用 Java 客戶端連接解析爲 localhost

host.name=your_ip
advertised.host.name=your_ip

其中,your_ip 配置爲服務器外網 IP。

2.3.2. Kafka

同樣在 config 配置文件下修改 server.properties 文件即可。

主要配置如下:

# 監聽
listeners=PLAINTEXT://服務器內網IP:9092

# 以下兩項類似 zookeeper 配置
advertised.listeners=PLAINTEXT://服務器外網IP:9092
host.name=外網IP

# zookeeper 連接信息
zookeeper.connect=zookeeper服務器IP:2181

2.4. 啓動

先啓動 zookeeper,因爲 Kafka 啓動的時候會連接註冊 zookeeper。

2.4.1. zookeeper

啓動 zookeeper,在 Kafka 根目錄執行

./bin/zookeeper-server-start.sh ./config/zookeeper.properties

上述方式,會佔有 shell 客戶端窗口,如果想後臺啓動,添加參數 daemon 即可

./bin/zookeeper-server-start.sh -daemon ./config/zookeeper.properties

2.4.2. kafka

類似 zookeeper 啓動。

./bin/kafka-server-start.sh ./config/server.properties

後臺啓動:

./bin/kafka-server-start.sh -daemon ./config/server.properties

此時 Kafka 單節點部署就已經完成了,通過 ps -ef | grep zookeeper, ps -ef | grep kafka 看到對應進程,證明啓動成功。

2.5. topic

2.5.1. 創建 topic

通過 Kafka 提供的腳本文件,即可創建。在 Kafka 根目錄下執行:

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

1)指定 zk 爲 localhost:2181
2)副本因子爲 1,即不需要副本
3)partition 數量爲 3
4)topic 名稱爲 top_name

2.5.2. 查看 topic

./bin/kafka-topics.sh --list --zookeeper localhost:2181
  1. list 命令用於查看
    2)需要指定 zk

2.6. 生產消費

此處直接通過 Kafka 提供的簡單客戶端進行生產消費數據。

2.6.1. 生產

1、啓動簡單 producer

./bin/kafka-console-producer.sh --broker-list localhost:9092 --topic topic_name

1) --broker-list 指定 Kafka 的地址及端口
2)–topic 指定具體 topic_name

2、 生產消息

直接在 producer 窗口輸入消息即可,消息是否發送成功,直接在 consumer 窗口即可查看。

2.6.2. 消費

1、啓動簡單 consumer

./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic_name --from-beginning

1)–bootstrap-server 指定 Kafka 地址及端口
2)-- topic 指定 topic
3)–from-beginning 表示指定從 offset 從頭開始消費

2、消費數據

直接在 producer 窗口發送消息,然後切換至 consumer 窗口,查看是否成功消費消息。

3. Java Client 生產消費

此步基於 SpringBoot 進行搭建 demo 項目。 SpringBoot 版本爲 2.x

3.1. 新建 SpringBoot 項目

直接通過 spring.starter 創建即可。完整項目: lambochen/demo/kafka

3.1.1. 引入依賴

Kafka 依賴:

<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

3.2. Kafka 配置

3.2.1. producer

1、application.properties 配置

kafka.producer.servers=kafka服務器IP:服務器端口號
kafka.producer.retries=0
kafka.producer.batch.size=4096
kafka.producer.linger=1
kafka.producer.buffer.memory=40960

kafka.topic.default=topic名稱

2、ProducerFactory, KafkaTemplate 配置:

public Map<String, Object> producerConfigs() {
    Map<String, Object> props = new LinkedHashMap<>();
    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
    props.put(ProducerConfig.RETRIES_CONFIG, retries);
    props.put(ProducerConfig.BATCH_SIZE_CONFIG,batchSize);
    props.put(ProducerConfig.LINGER_MS_CONFIG,linger);
    props.put(ProducerConfig.BUFFER_MEMORY_CONFIG,bufferMemory);
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class);
    return props;
}

public ProducerFactory<String, MessageEntity> producerFactory(){
    return new DefaultKafkaProducerFactory<>(
            producerConfigs(),
            new StringSerializer(),
            new JsonSerializer<MessageEntity>());
}

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

3.2.2. consumer

1、application.properties 配置

kafka.consumer.zookeeper.connect=ZK服務器端口:ZK端口
kafka.consumer.servers=Kafka服務器IP:Kafka端口
kafka.consumer.enable.auto.commit=true
kafka.consumer.session.timeout=6000
kafka.consumer.auto.commit.interval=100
kafka.consumer.auto.offset.reset=latest
kafka.consumer.topic=topic名稱
kafka.consumer.group.id=consumerGroup名稱
kafka.consumer.concurrency=10

2、KafkaListenerContainerFactory 配置

public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, MessageEntity>>
kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, MessageEntity> factory =
            new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());
    factory.setConcurrency(concurrency);
    factory.getContainerProperties().setPollTimeout(1500);
    return factory;
}

private ConsumerFactory<String, MessageEntity> consumerFactory() {
    return new DefaultKafkaConsumerFactory<>(
            consumerConfigs(),
            new StringDeserializer(),
            new JsonDeserializer<>(MessageEntity.class)
    );
}

private Map<String, Object> consumerConfigs() {
    Map<String, Object> propsMap = new HashMap<>();
    propsMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
    propsMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, enableAutoCommit);
    propsMap.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, autoCommitInterval);
    propsMap.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, sessionTimeout);
    propsMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    propsMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    propsMap.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
    propsMap.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset);
    return propsMap;
}

3.2.3. ProducerCallBack

生產回調,主要用於生產者發送消息後的處理。此 demo 僅作日誌記錄。

需要集成 ListenableFutureCallback ,並指定消息實體類型。

public class ProducerCallback implements ListenableFutureCallback<SendResult<String, MessageEntity>> 

其中, MessageEntity 爲消息實體類型。

3.3. 生產消息

創建 ProducerRecord 消息,通過 KafkaTemplate 發送即可。

@Autowired
@Qualifier("kafkaTemplate")
private KafkaTemplate<String, MessageEntity> kafkaTemplate;

public void send(String topic, MessageEntity message) {
    kafkaTemplate.send(topic, message);
}

public void send(String topic, String key, MessageEntity message) {
    ProducerRecord<String, MessageEntity> record = new ProducerRecord<>(topic, key, message);
    long startTime = System.currentTimeMillis();
    ListenableFuture<SendResult<String, MessageEntity>> future = kafkaTemplate.send(record);
    future.addCallback(new ProducerCallback(startTime, key, message));

}

3.4. 消費消息

消費消息,通過 @KafkaConsumer 註解即可實現。

@KafkaListener(topics = "${kafka.topic.default}", containerFactory = "kafkaListenerContainerFactory")
public void consumer(MessageEntity message){
    log.info("consumer: " + gson.toJson(message));
}

3.5. 測試

啓動 SpringBoot 項目,通過提供的 controller 進行請求生產消息。

查看日誌,成功記錄消息內容,即爲生產、消費成功。

到此爲止,Kafka demo 應用已完成啦

4. 踩坑記錄

4.1. 打印日誌

我在剛開始建好項目、配置 Kafka 後,啓動項目失敗,無日誌輸出,不好排查問題。

設置日誌 level, application.properties 文件配置:

logging.level.root=debug

4.2. kafka 啓動內存不足

kafka 啓動 報錯cannot allocate memory,即內存不足

4.3. java client 連接失敗

按照本教程配置,已經避免了這個問題。

【kafka】Java連接出現Connection refused: no further information

5. 參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章