区分如何在异步Kafka生产者中处理异常

时间:2020-06-30 18:01:40

标签: apache-kafka kafka-producer-api

向Kafka生成消息时,您会遇到两种错误:可重试错误和不可重试错误。处理它们时应如何区分它们?

我想异步生成记录,将callback object收到不可重试的异常的记录保存在另一个主题(或HBase)中,并让生产者为我处理所有接收到不可重试的异常的记录(最大数量)尝试,当它最终达到时,便成为最早的尝试之一。

我的问题是:尽管有callback object,生产者仍将自行处理可检索的异常吗? 因为在Interface Callback中说:

可恢复的异常(瞬态,可以通过增加#来覆盖 .retries)

可能是这样的代码吗?

producer.send(record, callback)

def callback: Callback = new Callback {
    override def onCompletion(recordMetadata: RecordMetadata, e: Exception): Unit = {
      if(null != e) {
         if (e == RecordTooLargeException || e == UnknownServerException || ..) {
            log.error("Winter is comming")
            writeDiscardRecordsToSomewhereElse
         } else {
            log.warn("It's no that cold") //it's retriable. The producer will keep trying by itself?
         }
      } else {
        log.debug("It's summer. Everything is fine")
      }
    }
}

Kafka版本:0.10.0

任何光将不胜感激! :)

1 个答案:

答案 0 :(得分:0)

正如卡夫卡圣经(又名Kafka-The Definitive Guide)所说:

缺点是,尽管commitSync()会重试提交,直到它提交为止 成功或遇到不可修复的失败,commitAsync() 不会重试。

原因:

它不会重试,直到commitAsync()收到一个 来自服务器的响应,可能是后来的提交 已经成功了。

想象一下,我们发送了一个提交偏移量的请求 2000。存在临时通信问题,因此代理永远不会收到请求,因此永远不会响应。同时,我们处理了 另一个批次并成功提交偏移量3000。 sync()现在重试先前失败的提交,它可能会成功执行 在偏移3000已经处理后提交偏移2000,并且 承诺。在重新平衡的情况下,这将导致更多 重复。

除此之外,您仍然可以创建一个递增的序列号,每次提交时都可以增加它,并将该数字添加到Callback对象中。重试时间到了,只需检查Acc的当前值是否等于您提供给Callback的数字即可。如果这样做,那是安全的,您可以执行提交。否则,将有一个新的提交,您不应重试此偏移量的提交。

似乎有很多麻烦,那是因为如果您正在考虑这一点,则应该更改策略。