简体   繁体   English

无法向kafka主题发送单个消息

[英]unable to send single message to kafka topic

I am using kafka java client 0.11.0 and kafka server 2.11-0.10.2.0 . 我正在使用kafka java客户端0.11.0和kafka服务器2.11-0.10.2.0

My code : 我的代码:

KafkaManager 卡夫卡经理

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;
        }
    }
}

Kafka Producer 卡夫卡制片人

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();
        }
    }
}

Main Class 主班

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);
        }
    }
}

What is my problem: 我的问题是什么:

When my loop length if around 1000 (in class App ), I am successfully able to send data to Kafka topic. 当我的循环长度大约为1000(在App类中)时,我就能够成功将数据发送到Kafka主题。

But when My loop length is 1 or less than 10, I am not able to send data to Kafka topic. 但是,当我的循环长度为1或小于10时,我无法将数据发送到Kafka主题。 Note I am not getting any error. 注意我没有任何错误。

According to my finding, If I want to send a single message to Kafka topic, According to this program I get the successful message but never get a message on my topic. 根据我的发现,如果我想向Kafka主题发送一条消息,则根据该程序,我会收到成功的消息,但从未收到有关该主题的消息。

But If I use Thread.sleep(10) (as you can see in my App class I have commented it), then I successfully send data on my topic. 但是,如果我使用Thread.sleep(10)(正如您在App类中看到的那样,我已经对其进行了注释),那么我就可以成功发送有关主题的数据。

Can you please explain why kafka showing this ambigous behabiour. 你能解释一下为什么卡夫卡表现出这种模棱两可的行为。

Each call to KafkaProducer.send() is returning a Future. 每次对KafkaProducer.send()的调用都返回一个Future。 You can use the last of those Futures to block the main Thread before exiting. 您可以在退出前使用这些期货中的最后一个来阻止主线程。 Even easier, you can just call KafkaProducer.flush() after sending all your messages: http://kafka.apache.org/0110/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html#flush() 甚至更容易,您可以在发送所有消息后直接调用KafkaProducer.flush(): http ://kafka.apache.org/0110/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html#flush ()

Invoking this method makes all buffered records immediately available to send (even if linger.ms is greater than 0) and blocks on the completion of the requests associated with these records. 调用此方法将使所有缓冲的记录立即可用于发送(即使linger.ms大于0),并在与这些记录关联的请求完成时阻塞。

Can you add Thread.sleep(100); 你可以添加Thread.sleep(100); just before exiting main? 就在退出main之前? If I understand correctly then everything works well if you sleep for a small amount of time. 如果我理解正确,那么如果您睡一小段时间,一切都会很好。 If that's the case, then it implies that your application is getting killed before the message is sent asynchronously. 如果是这种情况,则意味着在异步发送消息之前,您的应用程序已被终止。

You are facing the problem because the producer executes sending in async way. 您正面临问题,因为生产者以异步方式执行发送。 When you send, the message is put inside an internal buffer in order to get a bigger batch and then send more messages with one shot. 发送时,邮件将放入内部缓冲区中,以获取更大的批次,然后一次发送更多邮件。 This batching features is configured with batch.size and linger.ms, it means that messages are sent when the batch size reached that value or a linger time elapsed. 此批处理功能配置有batch.size和linger.ms,这意味着当批处理大小达到该值或经过一段较​​长时间后,将发送消息。

I have replied on something similar here : Cannot produce Message when Main Thread sleep less than 1000 我在这里回答了类似的问题: 主线程睡眠少于1000时无法生成消息

Even you are saying "When my loop length if around 1000 (in class App), I am successfully able to send data to Kafka topic." 即使您说的是“当我的循环长度大约为1000(在App类中)时,我也能够成功将数据发送到Kafka主题”。 ... but maybe you don't see all the sent messages because the latest batch isn't sent. ...但是您可能看不到所有已发送的消息,因为没有发送最新的批处理。 With shorter loop the above conditions aren't reached in time so you shutdown the application before producer has enough time/batch size for sending. 如果使用较短的循环,则无法及时达到上述条件,因此您可以在生产者有足够的时间/批处理大小发送之前关闭应用程序。

change this line inside server.properties from localhost to an IP Address: 将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