簡體   English   中英

無法向kafka主題發送單個消息

[英]unable to send single message to kafka topic

我正在使用kafka java客戶端0.11.0和kafka服務器2.11-0.10.2.0

我的代碼:

卡夫卡經理

public class KafkaManager {

    // Single instance for producer per topic
    private static Producer<String, String> karmaProducer = null;

    /**
     * Initialize Producer
     * 
     * @throws Exception
     */
    private static void initProducer() throws Exception {
        Properties props = new Properties();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, Constants.kafkaUrl);
        props.put(ProducerConfig.RETRIES_CONFIG, Constants.retries);
        //props.put(ProducerConfig.BATCH_SIZE_CONFIG, Constants.batchSize);
        props.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, Constants.requestTimeout);
        //props.put(ProducerConfig.LINGER_MS_CONFIG, Constants.linger);
        //props.put(ProducerConfig.ACKS_CONFIG, Constants.acks);
        //props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, Constants.bufferMemory);
        //props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, Constants.maxBlock);
        props.put(ProducerConfig.CLIENT_ID_CONFIG, Constants.kafkaProducer);
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        try {
            karmaProducer = new org.apache.kafka.clients.producer.KafkaProducer<String, String>(props);
        }
        catch (Exception e) {
            throw e;
        }
    }

    /**
     * get Producer based on topic
     * 
     * @return
     * @throws Exception
     */
    public static Producer<String, String> getKarmaProducer(String topic) throws Exception {
        switch (topic) {
        case Constants.topicKarma :
            if (karmaProducer == null) {
                synchronized (KafkaProducer.class) {
                    if (karmaProducer == null) {
                        initProducer();
                    }
                }
            }
            return karmaProducer;

        default:
            return null;
        }
    }

    /**
     * Flush and close kafka producer
     * 
     * @throws Exception
     */
    public static void closeKafkaInstance() throws Exception {
        try {
            karmaProducer.flush();
            karmaProducer.close();
        } catch (Exception e) {
            throw e;
        }
    }
}

卡夫卡制片人

public class KafkaProducer {

    public void sentToKafka(String topic, String data) {
        Producer<String, String> producer = null;
        try {
            producer = KafkaManager.getKarmaProducer(topic);
            ProducerRecord<String, String> producerRecord = new ProducerRecord<String, String>(topic, data);
            producer.send(producerRecord);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

主班

public class App {

    public static void main(String[] args) throws InterruptedException {

        System.out.println("Hello World! I am producing to stream " + Constants.topicKarma);
        String value = "google";
        KafkaProducer kafkaProducer = new KafkaProducer();
        for (int i = 1; i <= 1; i++) {
            kafkaProducer.sentToKafka(Constants.topicKarma, value + i);
            //Thread.sleep(100);
            System.out.println("Send data to producer=" + value);
            System.out.println("Send data to producer=" + value + i + " to tpoic=" +  Constants.topicKarma);
        }
    }
}

我的問題是什么:

當我的循環長度大約為1000(在App類中)時,我就能夠成功將數據發送到Kafka主題。

但是,當我的循環長度為1或小於10時,我無法將數據發送到Kafka主題。 注意我沒有任何錯誤。

根據我的發現,如果我想向Kafka主題發送一條消息,則根據該程序,我會收到成功的消息,但從未收到有關該主題的消息。

但是,如果我使用Thread.sleep(10)(正如您在App類中看到的那樣,我已經對其進行了注釋),那么我就可以成功發送有關主題的數據。

你能解釋一下為什么卡夫卡表現出這種模棱兩可的行為。

每次對KafkaProducer.send()的調用都返回一個Future。 您可以在退出前使用這些期貨中的最后一個來阻止主線程。 甚至更容易,您可以在發送所有消息后直接調用KafkaProducer.flush(): http ://kafka.apache.org/0110/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html#flush ()

調用此方法將使所有緩沖的記錄立即可用於發送(即使linger.ms大於0),並在與這些記錄關聯的請求完成時阻塞。

你可以添加Thread.sleep(100); 就在退出main之前? 如果我理解正確,那么如果您睡一小段時間,一切都會很好。 如果是這種情況,則意味着在異步發送消息之前,您的應用程序已被終止。

您正面臨問題,因為生產者以異步方式執行發送。 發送時,郵件將放入內部緩沖區中,以獲取更大的批次,然后一次發送更多郵件。 此批處理功能配置有batch.size和linger.ms,這意味着當批處理大小達到該值或經過一段較​​長時間后,將發送消息。

我在這里回答了類似的問題: 主線程睡眠少於1000時無法生成消息

即使您說的是“當我的循環長度大約為1000(在App類中)時,我也能夠成功將數據發送到Kafka主題”。 ...但是您可能看不到所有已發送的消息,因為沒有發送最新的批處理。 如果使用較短的循環,則無法及時達到上述條件,因此您可以在生產者有足夠的時間/批處理大小發送之前關閉應用程序。

將server.properties中的這一行從localhost更改為IP地址:

zookeeper.connect=localhost:2181

advertised.listeners=PLAINTEXT://localhost:9092

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM