Kafka 生產者

1.生產者消息發送流程

1.發送原理

在消息發送的過程中,涉及到了兩個線程——main 線程和 Sender 線程。在 main 線程中創建了一個雙端隊列 RecordAccumulator。main 線程將消息發送給 RecordAccumulator,Sender 線程不斷從 RecordAccumulator 中拉取消息發送到 Kafka Broker。

2.生產者重要參數列表

參數名稱 描述
bootstrap.servers 生產者連接集羣所需的 broker 地 址 清 單 。 例 如192.168.58.130:9092,192.168.58.131:9092,192.168.58.132:9092,可以設置 1 個或者多個,中間用逗號隔開。注意這裏並非需要所有的 broker 地址,因爲生產者從給定的 broker裏查找到其他 broker 信息
key.serializer 和 value.serializer 指定發送消息的 key 和 value 的序列化類型。一定要寫全類名
buffer.memory RecordAccumulator 緩衝區總大小,默認 32m
batch.size 緩衝區一批數據最大值,默認 16k。適當增加該值,可以提高吞吐量,但是如果該值設置太大,會導致數據傳輸延遲增加
linger.ms 如果數據遲遲未達到 batch.size,sender 等待 linger.time之後就會發送數據。單位 ms,默認值是 0ms,表示沒有延遲。生產環境建議該值大小爲 5-100ms 之間
acks 0:生產者發送過來的數據,不需要等數據落盤應答。
1:生產者發送過來的數據,Leader 收到數據後應答。
-1(all):生產者發送過來的數據,Leader+和 isr 隊列裏面的所有節點收齊數據後應答。
默認值是-1,-1 和all 是等價的
max.in.flight.requests.per.connection 允許最多沒有返回 ack 的次數,默認爲 5,開啓冪等性要保證該值是 1-5 的數字
retries 當消息發送出現錯誤的時候,系統會重發消息。retries表示重試次數。默認是 int 最大值,2147483647。如果設置了重試,還想保證消息的有序性,需要設置MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION=1否則在重試此失敗消息的時候,其他的消息可能發送成功了。
retry.backoff.ms 兩次重試之間的時間間隔,默認是 100ms
enable.idempotence 是否開啓冪等性,默認 true,開啓冪等性
compression.type 生產者發送的所有數據的壓縮方式。默認是 none,也就是不壓縮。
支持壓縮類型:none、gzip、snappy、lz4 和 zstd。

2.發送API

在操作API之前,需要先創建Java的Maven項目,並引入相關的依賴,其中的核心便是kafka-clients

        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>3.6.1</version>
        </dependency>

1.異步發送 API

1.普通異步發送

package cn.coreqi.kafka.producer;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;

public class CustomProducer {
    public static void main(String[] args) {
        // 1. 創建 kafka 生產者的配置對象
        Properties properties = new Properties();
        // 2. 給 kafka 配置對象添加配置信息:bootstrap.servers
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.58.130:9092");

        // key,value 序列化(必須):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
                "org.apache.kafka.common.serialization.StringSerializer");

        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
                "org.apache.kafka.common.serialization.StringSerializer");

        // 3. 創建 kafka 生產者對象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);
        // 4. 調用 send 方法,發送消息
        for (int i = 0; i < 5; i++) {
            kafkaProducer.send(new ProducerRecord<>("first","coreqi " + i));
        }
        // 5. 關閉資源
        kafkaProducer.close();
    }
}

2.帶回調函數的異步發送

回調函數會在 producer 收到 ack 時調用,爲異步調用,該方法有兩個參數,分別是元數據信息(RecordMetadata)和異常信息(Exception),如果 Exception 爲 null,說明消息發送成功,如果 Exception 不爲 null,說明消息發送失敗。

注意:消息發送失敗會自動重試,不需要我們在回調函數中手動重試。

package cn.coreqi.kafka.producer;

import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;

public class CustomProducerCallback {
    public static void main(String[] args) throws InterruptedException {
        // 1. 創建 kafka 生產者的配置對象
        Properties properties = new Properties();
        // 2. 給 kafka 配置對象添加配置信息
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.58.130:9092");

        // key,value 序列化(必須):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
                StringSerializer.class.getName());

        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
                StringSerializer.class.getName());

        // 3. 創建 kafka 生產者對象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);

        // 4. 調用 send 方法,發送消息
        for (int i = 0; i < 5; i++) {
            // 添加回調
            kafkaProducer.send(new ProducerRecord<>("first", "coreqi " + i), new Callback() {
                // 該方法在 Producer 收到 ack 時調用,爲異步調用
                @Override
                public void onCompletion(RecordMetadata metadata, Exception exception) {
                    if (exception == null) {
                        // 沒有異常,輸出信息到控制檯
                        System.out.println(" 主題: " +
                                metadata.topic() + "->" + "分區:" + metadata.partition());
                    } else {
                        // 出現異常打印
                        exception.printStackTrace();
                    }
                }
            });
            // 延遲一會會看到數據發往不同分區
            Thread.sleep(2);
        }
        // 5. 關閉資源
        kafkaProducer.close();
    }
}

2.同步發送 API

只需在異步發送的基礎上,再調用一下 get()方法即可。

package cn.coreqi.kafka.producer;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;
import java.util.concurrent.ExecutionException;

public class CustomProducerSync {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. 創建 kafka 生產者的配置對象
        Properties properties = new Properties();
        
        // 2. 給 kafka 配置對象添加配置信息
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.58.130:9092");
        
        // key,value 序列化(必須):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
                StringSerializer.class.getName());

        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
                StringSerializer.class.getName());

        // 3. 創建 kafka 生產者對象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);
        
        // 4. 調用 send 方法,發送消息
        for (int i = 0; i < 10; i++) {
            // 異步發送 默認
            // kafkaProducer.send(new ProducerRecord<>("first","kafka" + i));
            // 同步發送
            kafkaProducer.send(new ProducerRecord<>("first","kafka" + i)).get();
        }
        // 5. 關閉資源
        kafkaProducer.close();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章