繁体   English   中英

如何确保已删除 Kafka 主题?

[英]How can I make sure that a Kafka topic has been deleted?

不幸的是,Kafka 的Admin.deleteTopics API 仅在收到请求后才返回 - 这仅意味着主题已被集群安排删除,但不一定现在已删除。

举个例子,下面的代码经常会抛出:

final var newTopic = new NewTopic("aaa", Optional.empty(), Optional.empty());
this.admin.createTopics(Collections.singleton(newTopic), opt).all().get();
this.admin.deleteTopics(Arrays.asList("aaa")).all().get();
this.admin.listTopics( ).names().get().contains("aaa"); // Returns 'false'.
this.admin.createTopics(Collections.singleton(newTopic), opt).all().get(); // <- throws

有一个例外:

java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.TopicExistsException: Topic 'aaa' is marked for deletion.
    at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
    at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999)
    at org.apache.kafka.common.internals.KafkaFutureImpl.get(KafkaFutureImpl.java:165)
...
Caused by: org.apache.kafka.common.errors.TopicExistsException: Topic 'aaa' is marked for deletion.

不幸的是Admin.listTopics()在这里没有帮助,提交删除请求后主题不再可见。

所以问题是 - 是否有任何编程方式(最好是 API)可以让我们监控该主题是否真的消失了?

使用的 Kafka(客户端和服务器)版本是 3.2。

到目前为止,我还没有在 API 中发现任何有趣的东西,但我有一些可能的想法,不幸的是它们都很丑陋。

  1. 每个主题似乎都有多个与其大小相关的度量 bean,例如kafka.log:type=Log,name=LogStartOffset,topic=aaa,partition=0 所以我们可以等到它们消失。 但是,为了完全确定,我们可能需要检查所有代理(或至少:所有副本托管代理)。

  2. 代理实例似乎有一个名为kafka.controller:type=KafkaController,name=TopicsToDeleteCount的 bean,这可能是我们想要的,但是没有细粒度的控制。 而且我们可能仍然需要检查集群中的所有代理并等待它们都达到 0。

  3. 查看内部 Zookeeper / KRaft 结构。 有趣的部分可能出现在/brokers/topics/admin/delete_topics等路径中,但这意味着带来另一个(Zookeeper)依赖项。 KRaft 是一个类似的案例,我们将挖掘经纪人的内部结构。

删除主题后创建一个foo主题,这可能会加快 Kafka 删除速度。 然后创建有用的主题。 我的测试发现有一定的效果。

public void reCreateTopics(Set<String> topics) {
    adminClient.deleteTopics(topics).all().get();
    createFooTopic4TriggeringDelete();

    // may be sleep 1s before creating
    TimeUnit.SECONDS.sleep(1);

    adminClient.createTopics(topics).all().get();
}


private void createFooTopic4TriggeringDelete()  {
    NewTopic foo = new NewTopic("foo_" + System.currentTimeMillis(), 1, (short) 1);
    adminClient.createTopics(Collections.singleton(foo)).all().get();
    adminClient.deleteTopics(Collections.singleton(foo.name())).all().get();
}

暂无
暂无

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

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