搭建Kafka簡單教程

1.前言:

本文只是簡單介紹如何搭建kafka,關於kafka的詳細內容,此文暫時不講。

2.Kafka簡介

Kafka是分佈式發佈-訂閱消息系統,它最初由 LinkedIn 公司開發,使用 Scala語言編寫,之後成爲 Apache 項目的一部分。在Kafka集羣中,沒有“中心主節點”的概念,集羣中所有的服務器都是對等的,因此,可以在不做任何配置的更改的情況下實現服務器的的添加與刪除,同樣的消息的生產者和消費者也能夠做到隨意重啓和機器的上下線。

2.1.Kafka術語介紹

1.消息生產者:即:Producer,是消息的產生的源頭,負責生成消息併發送到Kafka服務器上。

2.消息消費者:即:Consumer,是消息的使用方,負責消費Kafka服務器上的消息。

3.主題:即:Topic,由用戶定義並配置在Kafka服務器,用於建立生產者和消息者之間的訂閱關係:生產者發送消息到指定的Topic下,消息者從這個Topic下消費消息。

4.消息分區:即:Partition,一個Topic下面會分爲很多分區,例如:“kafka-test”這個Topic下可以分爲6個分區,分別由兩臺服務器提供,那麼通常可以配置爲讓每臺服務器提供3個分區,假如服務器ID分別爲0、1,則所有的分區爲0-0、0-1、0-2和1-0、1-1、1-2。Topic物理上的分組,一個 topic可以分爲多個 partition,每個 partition 是一個有序的隊列。partition中的每條消息都會被分配一個有序的 id(offset)。

5.Broker:即Kafka的服務器,用戶存儲消息,Kafa集羣中的一臺或多臺服務器統稱爲 broker。

6.消費者分組:Group,用於歸組同類消費者,在Kafka中,多個消費者可以共同消息一個Topic下的消息,每個消費者消費其中的部分消息,這些消費者就組成了一個分組,擁有同一個分組名稱,通常也被稱爲消費者集羣。

7.Offset:消息存儲在Kafka的Broker上,消費者拉取消息數據的過程中需要知道消息在文件中的偏移量,這個偏移量就是所謂的Offset。

3.搭建Kafka
 

3.1. 安裝JDK
3.1.1 安裝文件:http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html下載Server JRE.
3.1.2 安裝完成後需要添加以下的環境變量(右鍵點擊“我的電腦” -> "高級系統設置" -> "環境變量" ):
<1>.JAVA_HOME: C:\Program Files (x86)\Java\jre1.8.0_60(這個是默認安裝路徑,如果安裝過程中更改了安裝目錄,把更改後的路徑填上就行了)
<2>.PATH: 在現有的值後面添加"; %JAVA_HOME%\bin"
3.1.3 打開cmd運行 "java -version" 查看當前系統Java的版本:
3.2. 安裝Zookeeper
Kafka的運行依賴於Zookeeper,所以在運行Kafka之前我們需要安裝並運行Zookeeper
3.2.1 下載安裝文件: http://zookeeper.apache.org/releases.html
3.2.2 解壓文件(本文解壓到 D:\Software\Devolopment\zookeeper-3.4.14)
3.2.3 打開D:\Software\Devolopment\zookeeper-3.4.14\conf,把zoo_sample.cfg重命名成zoo.cfg
3.2.4 從文本編輯器裏打開zoo.cfg
3.2.5 把dataDir的值改成“D:\Software\Devolopment\zookeeper-3.4.14\data”
3.2.6 添加如下系統變量:
<1>.ZOOKEEPER_HOME: D:\Software\Devolopment\zookeeper-3.4.14
<2>.Path: 在現有的值後面添加";%ZOOKEEPER_HOME%\bin;"
3.2.7 運行Zookeeper: 打開cmd然後執行zkserver
3.3. 安裝並運行Kafka
3.3.1 下載安裝文件: http://kafka.apache.org/downloads.html
3.3.2 解壓文件(本文解壓到 D:\Software\Devolopment\kafka_2.12-0.10.2.2)
3.3.3 打開D:\Software\Devolopment\kafka_2.12-0.10.2.2\config
3.3.4 從文本編輯器裏打開 server.properties
3.3.5 把log.dirs的值改成 “D:\Software\Devolopment\kafka_2.12-0.10.2.2\kafka-logs”
3.3.6 打開cmd
3.3.7 進入kafka文件目錄: cd /d D:\Software\Devolopment\kafka_2.12-0.10.2.2
3.3.8 輸入並執行以打開kafka:
.\bin\windows\kafka-server-start.bat .\config\server.properties
3.4. 創建topics
3.4.1 打開cmd 並進入D:\Software\Devolopment\kafka_2.12-0.10.2.2\bin\windows
3.4.2 創建一個topic:
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
3.5.打開一個Producer:
cd D:\Software\Devolopment\kafka_2.12-0.10.2.2\bin\windows
kafka-console-producer.bat --broker-list localhost:9092 --topic test
3.6. 打開一個Consumer:
cd D:\Software\Devolopment\kafka_2.12-0.10.2.2\bin\windows
kafka-console-consumer.bat --zookeeper localhost:2181 --topic test
然後就可以在Producer控制檯窗口輸入消息了。在消息輸入過後,很快Consumer窗口就會顯示出Producer發送的消息。
Kafka運行環境的搭建就完成了。

4.代碼實現

需要建一個springboot項目,並導入相關依賴。

4.1 添加依賴

<dependency>
   <groupId>org.springframework.kafka</groupId>
   <artifactId>spring-kafka</artifactId>
</dependency>

4.2 配置

package com.example.kafka.kafka2;

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.config.KafkaListenerContainerFactory;
import org.springframework.kafka.core.*;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;

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

@Configuration
@EnableKafka
public class KafkaConfig {

    @Value("${spring.kafka.server}")
    private String kafkaServer;

    @Value("${spring.kafka.group}")
    private String kafkaGroup;

    public Map<String, Object> consumerConfig(String consumerGroupId){
        Map<String, Object> props = new HashMap<>();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServer);
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "100");
        props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "15000");
        props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupId);
        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;
    }
    public ConsumerFactory<String, String> consumerFactory(String consumerGroupId) {
        return new DefaultKafkaConsumerFactory<>(consumerConfig(consumerGroupId));
    }

    public Map<String, Object> producerConfig(){
        Map<String, Object> props = new HashMap<>();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServer);
        props.put(ProducerConfig.RETRIES_CONFIG, 0);
        props.put(ProducerConfig.BATCH_SIZE_CONFIG, 1000);
        props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
        props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 40960);
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        return props;
    }

    public ProducerFactory<String, String> producerFactory(){
        return new DefaultKafkaProducerFactory<>(producerConfig());
    }


    @Bean(name="kafkaListenerContainerFactory")
    public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory(kafkaGroup));
        factory.setConcurrency(3);
        factory.getContainerProperties().setPollTimeout(3000);
        return factory;
    }

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

}

4.3 生產者

package com.example.kafka.kafka2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class KafkaSender {
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Value("${spring.kafka.topic}")
    private String topic;

    private int index;
    public void sendTest(){
        String msg = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
        kafkaTemplate.send(topic,"hello,kafka"+index + ":" + msg);
        System.out.println("hello,kafka"+index + ":" + msg);
        index ++;

    }
}

4.4 消費者

package com.example.kafka.kafka2;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

@Component
public class KafkaConsumer {

    /**
     * 監聽test主題,有消息就讀取
     * @param message
     */
    @KafkaListener(topics="${spring.kafka.topic}",containerFactory="kafkaListenerContainerFactory")
    public void consumer(String message){
        System.out.println("receiveMaching1:"+ message);
    }
}

 

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