kafka异步产生丢失的消息

时间:2020-04-20 12:20:21

标签: apache-kafka kafka-producer-api

尝试按照互联网上的说明来实现kafka异步生成。这是我的制作人的样子:

import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
public void asynSend(String topic, Integer partition, String message) {
    ProducerRecord<Object, Object> data = new ProducerRecord<>(topic, partition,null, message);
        producer.send(data, new DefaultProducerCallback());
    }

private static class DefaultProducerCallback implements Callback {
    @Override
    public void onCompletion(RecordMetadata recordMetadata, Exception e) {
        if (e != null) {
            logger.error("Asynchronous produce failed");
        }
    }
}

然后在这样的for循环中产生:

for (int i = 0; i < 5000; i++) {
    int partition = i % 2;
    FsProducerFactory.getInstance().asynSend(topic, partition,i + "th message to partition " + partition);
}

但是,某些消息可能会丢失。如下所示,从4508到4999的消息未传递。

enter image description here

我发现原因可能是生产者进程关闭,并且当时未发送的所有缓存消息都将丢失。 在for循环之后添加此行将解决此问题:

producer.flush();

但是,我不确定这是否是一个吸引人的解决方案,因为我注意到有人提到同花顺将使异步以某种方式发送同步,任何人都可以解释或帮助我改进它吗?

1 个答案:

答案 0 :(得分:0)

Kafka - The definitive Guide书中,有一个示例,说明了一个与您编写代码完全相同的异步生产者。它与send一起使用Callback

discussion中这样写:

在退出之前添加flush()将使客户端等待任何未完成的消息传递到代理(这将是queue.buffering.max.ms左右,外加延迟)。 如果在每个flush()调用之后添加produce(),则实际上是在实现同步生成器。

但是如果您在for循环之后 这样做,它将不再是同步的,而是异步的。

您还可以做的是将Producer配置中的acks设置为all。这样,在主题的复制设置为大于1的情况下,您将有更多保证成功生成消息。