繁体   English   中英

如何以稳健的方式处理 kafka 发布失败

[英]How to handle kafka publishing failure in robust way

我正在使用 Kafka,我们有一个用例来构建一个容错系统,其中一条消息都不应该被遗漏。 所以这里的问题是:如果由于任何原因(ZooKeeper 关闭、Kafka 代理关闭等)发布到 Kafka 失败,我们如何稳健地处理这些消息并在事情再次恢复后重播它们。 再次正如我所说,我们甚至无法承受一条消息失败。 另一个用例是我们还需要在任何给定的时间点知道有多少消息由于任何原因而未能发布到 Kafka,例如计数器功能之类的东西,现在这些消息需要再次重新发布。

解决方案之一是将这些消息推送到某个数据库(例如 Cassandra,其中写入速度非常快,但我们也需要计数器功能,我猜 Cassandra 计数器功能不是那么好,我们不想使用它。)它可以处理那种负载,还为我们提供了非常准确的计数器设施。

这个问题更多是从架构的角度来看,然后是使用哪种技术来实现这一点。

PS:我们处理一些像 3000TPS 的地方。 因此,当系统开始失败时,这些失败的消息会在很短的时间内快速增长。 我们正在使用基于 Java 的框架。

感谢您的帮助!

Kafka采用分布式、容错的方式构建的原因是为了处理和你一样的问题,核心组件的多个故障应该避免服务中断。 为避免 Zookeeper 宕机,请至少部署 3 个 Zookeeper 实例(如果在 AWS 中,请跨可用区部署它们)。 为避免代理失败,请部署多个代理,并确保在生产者bootstrap.servers属性中指定多个代理。 为确保 Kafka 集群以持久的方式写入您的消息,请确保在生产者中设置acks=all属性。 当所有同步副本确认接收到消息(以吞吐量为代价)时,这将确认客户端写入。 您还可以设置排队限制以确保如果写入代理开始备份,您可以捕获异常并处理它并可能重试。

使用 Cassandra(另一个经过深思熟虑的分布式容错系统)来“暂存”您的写入似乎并没有为您的架构增加任何可靠性,但确实增加了复杂性,而且 Cassandra 没有被编写为消息队列消息队列,我会避免这种情况。

正确配置后,Kafka 应该可用于处理您的所有消息写入并提供适当的保证。

我参加聚会超级迟到。 但我发现上面的答案中缺少一些东西:)

选择像 Cassandra 这样的分布式系统的策略是一个不错的主意。 一旦Kafka启动并正常,您可以重试写入其中的所有消息。

我想从“知道有多少消息在给定时间发布失败”来回答

从标签中,我看到您正在使用apache-kafkakafka-consumer-api 。您可以为您的生产者编写一个自定义回调,这个回调可以告诉您消息是失败还是成功发布。 失败时,记录消息的元数据。

现在,您可以使用日志分析工具来分析您的故障。 Splunk 就是这样一种不错的工具。

下面是一个小代码片段,可以更好地解释我正在谈论的回调:

public class ProduceToKafka {

  private ProducerRecord<String, String> message = null;

 // TracerBulletProducer class has producer properties
  private KafkaProducer<String, String> myProducer = TracerBulletProducer
      .createProducer();

  public void publishMessage(String string) {

    ProducerRecord<String, String> message = new ProducerRecord<>(
        "topicName", string);

    myProducer.send(message, new MyCallback(message.key(), message.value()));
  }

  class MyCallback implements Callback {

    private final String key;
    private final String value;

    public MyCallback(String key, String value) {
      this.key = key;
      this.value = value;
    }


    @Override
    public void onCompletion(RecordMetadata metadata, Exception exception) {
      if (exception == null) {
        log.info("--------> All good !!");
      } else {
        log.info("--------> not so good  !!");
        log.info(metadata.toString());
        log.info("" + metadata.serializedValueSize());
        log.info(exception.getMessage());

      }
    }
  }

}

如果你分析"--------> not so good !!" 每个时间单位的日志,您可以获得所需的见解。

神速!

Chris 已经讲过如何保持系统容错。

Kafka 默认支持at-least once消息传递语义,这意味着当它尝试发送消息时,它会尝试重新发送它。

当您创建Kafka Producer属性时,您可以通过将retries选项设置为大于 0 来进行配置。

 Properties props = new Properties();
 props.put("bootstrap.servers", "localhost:4242");
 props.put("acks", "all");
 props.put("retries", 0);
 props.put("batch.size", 16384);
 props.put("linger.ms", 1);
 props.put("buffer.memory", 33554432);
 props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
 props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

 Producer<String, String> producer = new KafkaProducer<>(props);

有关更多信息,请检查

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM