【问题标题】:What is the best way to detect that a Kafka cluster is down?检测 Kafka 集群已关闭的最佳方法是什么?
【发布时间】:2020-06-10 22:55:35
【问题描述】:

Kafka 消费者 API 非常好,可以隐藏任何暂时的连接错误,并且如果 Kafka 代理死亡并再次出现,只需从其当前偏移量中读取数据。

但在某些应用程序中,如果整个 Kafka 集群已关闭(即所有代理),则发出警报并停止处理数据(来自其他来源)很重要。 我浏览了杂项。 API,这似乎不是一项功能。

我最接近的方法是提交管理员调用,并根据超时得出 Kafka 集群已关闭的结论:

Properties properties   = ... // Load properties from somewhere.
int timeout             = 5_000; // 5 second timeout
AdminClient adminClient = AdminClient.create(properties);
try {
    adminClient.listTopics(new ListTopicsOptions().timeoutMs(timeout)).listings().get();
    // Here we know the cluster is up as call returned within timeout.
} catch (ExecutionException ex) {
    // Here we know that the cluster is down as the call timed out.
}

这是最好的方法吗?

另一种方法是查询 ZooKeeper,但上述方法也适用于应用程序和 Kafka 之间存在网络问题的情况。

【问题讨论】:

  • 您的具体用例是什么?通常,“Kafka 集群已关闭”是一项监控任务,而不是针对消费者软件的任务。
  • 假设我有一个通过 Kafka 控制的应用程序,如果 Kafka 出现故障,它需要停止运行。 (单独监控很容易)。
  • 消费者无论如何都会抛出异常,但会继续重试,假设你使用了一个while循环并且没有断路器
  • 我会避免查询 Zookeeper 并观看 kip500

标签: java apache-kafka


【解决方案1】:

虽然我建议您使用适当的监控工具,但如果您仍想以编程方式执行此操作,一种选择是使用 AdminClient 并尝试获取主题名称。


例如,

Properties properties = new Properties();
properties.put("bootstrap.servers", "localhost:9092");
properties.put("request.timeout.ms", 5000);

try {

    AdminClient adminClient = AdminClient.create(properties)

    ListTopicsResult topics = adminClient.listTopics();
    Set<String> names = topics.names().get();

} catch(InterruptedException | ExecutionException e) {
    System.err.println("Kafka is unavailable");
}

但是请注意,如果某些代理关闭,上述内容不会引发异常(但显然,如果代理关闭并不意味着 Kafka 集群本身已关闭,因为数据应该仍然可以访问)

【讨论】:

  • 这可以扩展为描述消费者分配的主题并验证至少满足 minISR...这是消费者的最佳健康检查
【解决方案2】:

您的方法看起来不错。类似的方法(使用 Spring 的 HealthIndicator 的概念)是 MartinX3 所做的 here

他的解决方案:

@Component
public class KafkaHealthIndicator implements HealthIndicator {
    private final Logger log = LoggerFactory.getLogger(KafkaHealthIndicator.class);

    private KafkaTemplate<String, String> kafka;

    public KafkaHealthIndicator(KafkaTemplate<String, String> kafka) {
        this.kafka = kafka;
    }

    /**
     * Return an indication of health.
     *
     * @return the health for
     */
    @Override
    public Health health() {
        try {
            kafka.send("kafka-health-indicator", "❥").get(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            return Health.down(e).build();
        }
        return Health.up().build();
    }
}

您可能还希望在返回 Health.up().build()(例如 ActiveControllerCount = 0)之前结合其他 metric-checks,具体取决于您认为对您的用例而言重要的内容以将整个集群视为已关闭.

【讨论】:

  • 能够写入和复制数据对于消费者来说并不是最好的健康检查
  • 非常感谢@OneCricketeer,我们随时欢迎您的建议。您将如何改进上述内容?
  • 我对另一个答案的评论是我将如何处理它。检查应该是测试数据是否能够被消费,这意味着副本可用
  • 非常感谢@OneCricketeer,非常感谢:)
猜你喜欢
  • 1970-01-01
  • 2019-12-21
  • 2019-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 1970-01-01
相关资源
最近更新 更多