Kafka Producer:处理带有回调的异步发送中的异常

时间:2019-05-17 11:02:56

标签: apache-kafka kafka-producer-api

如果异步发送到Kafka,我需要捕获异常。 Kafka制作人Api附带了一个函数send(ProducerRecord record,Callback callback)。但是,当我针对以下两种情况进行测试时:

  • Kafka Broker Down
  • 主题未预先创建 回调不会被调用。相反,我在代码中收到发送不成功的警告(如下所示)。

问题:

  • 那么仅针对特定异常才调用回调吗?

  • Kafka Client何时在异步发送时尝试连接到Kafka代理:在每批发送中还是定期发送?

Kafka Warning Image

注意:我还使用linger.ms设置25秒来批量发送记录。


public class ProducerDemo {

    static KafkaProducer<String, String> producer;

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

         final Logger logger = LoggerFactory.getLogger(ProducerDemo.class);
        Properties properties = new Properties();
        properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:9092");
        properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.setProperty(ProducerConfig.ACKS_CONFIG, "1");
        properties.setProperty(ProducerConfig.LINGER_MS_CONFIG, "30000");

        producer = new KafkaProducer<String, String>(properties);
        String topic = "first_topic";

        for (int i = 0; i < 5; i++) {
            String value = "hello world " + Integer.toString(i);
            String key = "id_" + Integer.toString(i);

            ProducerRecord<String, String> record = new ProducerRecord<String, String>(topic, key, value);

              producer.send(record, new Callback() {
                    public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                        //execute everytime a record is successfully sent or exception is thrown
                        if(e == null){
                           // No Exception
                        }else{
                            //Exception Handling
                        }
                    }
                });
        }
        producer.close();
    }

3 个答案:

答案 0 :(得分:0)

对于第一个问题,这是答案。 根据apache kafka文档,在实现回调接口时,可以使用onCompletion方法捕获以下异常

https://kafka.apache.org/25/javadoc/org/apache/kafka/clients/producer/Callback.html

对于第二个问题,以下属性的组合控制何时发送记录,据我了解,同步或异步调用都相同。

linger.ms max.block.ms

https://kafka.apache.org/documentation/#linger.ms

答案 1 :(得分:0)

<块引用>

那么回调是否只针对特定异常调用?

是的,这就是它的工作原理。来自文档 (2.5.0):

     * Fully non-blocking usage can make use of the {@link Callback} parameter to provide a callback that
     * will be invoked when the request is complete.

注意重要的部分:请求完成时,这意味着生产者必须接受记录并将ProduceRequest发送给Kafka Broker。在不深入研究内部的情况下,这意味着必须存在代理元数据并且必须存在分区。

当涉及到正式规范时,您需要仔细查看 send() 的 Javadoc 以及 KafkaProducer 的 doSend 方法实现。在那里,您将看到在提交调用中可以抛出多个异常(而不是返回未来并调用回调),例如:

  • 如果代理元数据在给定的超时时间内不可用,
  • 如果数据无法序列化,
  • 如果序列化表单太大等

答案 2 :(得分:0)

您将收到针对不存在主题的警告,作为 KafkaProducer 提供的弹性机制。如果您等待更长时间(默认情况下应为 60 秒),最终将调用回调: 这是我的片段: enter image description here

因此,当出现问题并且异步发送不成功时,它将最终失败并导致未来失败或/和回调异常。 如果您不是以事务方式运行它,则仍然可能意味着批处理中的某些消息已找到到达代理的方式,而其他消息则没有。 如果每条发送到 Kafka 的消息都需要对上游系统(如 http 摄取接口等)进行阻塞式确认,这肯定会成为一个问题。做到这一点的唯一方法是使用未来的 get 阻止每条消息,如 documentation 中所述: enter image description here

总的来说,我注意到很多与 KafkaProducer 交付语义和保证相关的问题。绝对可以更好地记录它。

还有一件事,因为你提到了linger.ms

<块引用>

请注意,到达时间相近的记录通常会 即使与 linger.ms=0 一起批处理,因此在重负载下批处理将 无论延迟配置如何,都会发生