kafka如何获取所有topic kafka如何获取集群信息

本文介绍了三种查询Kafka主题的方法:通过KafkaConsumer对象的listTopics()方法;使用kafka-topics脚本;以及直接使用自定义的网络请求处理类TopicRequestHandle。每种方法都提供了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我使用的是0.10.1版本

方法一

public class KafkaConsumer<K, V> implements Consumer<K, V> {
        @Override
    public Map<String, List<PartitionInfo>> listTopics() {
        acquire();
        try {
            return fetcher.getAllTopicMetadata(requestTimeoutMs);
        } finally {
            release();
        }
    }
}

通过构造kafkaConsumer对象,调用 listTopic()方法,kafkaConsumer是消费者的入口类,怎么构造这里就不具体讲了.

方法二

kafka-topics脚本 大家可以通过shell命令来查看kafka的所有topic 这个命令的入口类为

 def main(args: Array[String]): Unit = {

    val opts = new TopicCommandOptions(args)

    if(args.length == 0)
      CommandLineUtils.printUsageAndDie(opts.parser, "Create, delete, describe, or change a topic.")

    // should have exactly one action
    val actions = Seq(opts.createOpt, opts.listOpt, opts.alterOpt, opts.describeOpt, opts.deleteOpt).count(opts.options.has _)
    if(actions != 1)
      CommandLineUtils.printUsageAndDie(opts.parser, "Command must include exactly one action: --list, --describe, --create, --alter or --delete")

    opts.checkArgs()

    val zkUtils = ZkUtils(opts.options.valueOf(opts.zkConnectOpt),
                          30000,
                          30000,
                          JaasUtils.isZkSecurityEnabled())
    var exitCode = 0
    try {
      if(opts.options.has(opts.createOpt))
        createTopic(zkUtils, opts)
      else if(opts.options.has(opts.alterOpt))
        alterTopic(zkUtils, opts)
      else if(opts.options.has(opts.listOpt))
        listTopics(zkUtils, opts)
      else if(opts.options.has(opts.describeOpt))
        describeTopic(zkUtils, opts)
      else if(opts.options.has(opts.deleteOpt))
        deleteTopic(zkUtils, opts)
    } catch {
      case e: Throwable =>
        println("Error while executing topic command : " + e.getMessage)
        error(Utils.stackTrace(e))
        exitCode = 1
    } finally {
      zkUtils.close()
      System.exit(exitCode)
    }

  }

相信根据这个类也可以很方便的改写,得到消息.

方法三

我最近看 Apache Kafka源码剖析 这本书,kafka自己定义了一套协议,只要遵循这套协议,就可以用任何语言与kafka通信了.所以查询 kafka的集群信息也有一个协议. 本来想利用它的 NetWorkClient来通信,过于复杂.于是用nio,简单写了一个方法,实现获取所有的集群信息.

/*
 * Copyright 2013-2018 Lilinfeng.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.kafka.clients.producer;

import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.network.NetworkReceive;
import org.apache.kafka.common.network.Send;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.ProtoUtils;
import org.apache.kafka.common.protocol.types.Struct;
import org.apache.kafka.common.requests.MetadataResponse;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class TopicRequestHandle implements Runnable {

    private String host;
    private int port;
    private NetworkReceive receive;
    private Send send;
    Cluster cluster = null;

    private Selector selector;
    private SocketChannel socketChannel;

    public TopicRequestHandle(String host, int port) {
        this.host = host == null ? "127.0.0.1" : host;
        this.port = port;
        try {
            selector = Selector.open();
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        try {
            doConnect();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        while (cluster==null) {
            try {
                selector.select(1000);
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectedKeys.iterator();
                SelectionKey key = null;
                while (it.hasNext()) {
                    key = it.next();
                    it.remove();
                    try {
                        handleInput(key);
                    } catch (Exception e) {
                        e.printStackTrace();
                        if (key != null) {
                            key.cancel();
                            if (key.channel() != null)
                                key.channel().close();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }

        // 多路复用器关闭后,所有注册在上面的Channel和Pipe等资源都会被自动去注册并关闭,所以不需要重复释放资源
        if (selector != null)
            try {
                selector.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

    }

    private void handleInput(SelectionKey key) throws IOException {

        if (key.isValid()) {
            // 判断是否连接成功
            SocketChannel sc = (SocketChannel) key.channel();
            if (key.isConnectable()) {
                if (sc.finishConnect()) {
                    sc.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
                } else
                    System.exit(1);// 连接失败,进程退出
            }
            if (key.isReadable()) {
                if (receive == null) {
                    receive = new NetworkReceive(-1, "-1");
                }
                receive.readFrom(socketChannel);
                if(receive.complete()){
                    ByteBuffer payload = receive.payload();
                    payload.rewind();
                    short apiKey = ApiKeys.METADATA.id;
                    short apiVer = ProtoUtils.latestVersion(apiKey);
                    Struct responseBody = ProtoUtils.responseSchema(apiKey, apiVer).read(receive.payload());
                    MetadataResponse response = new MetadataResponse(responseBody);
                   cluster = response.cluster();
                }
            }
            if(key.isWritable()){
                send.writeTo(socketChannel);
                if(send.completed()){
                    key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
                }
               // System.out.println(send.completed());
            }
        }

    }

    public void doConnect() throws IOException {
        //这里是异步IO
        // 如果直接连接成功,则注册到多路复用器上,发送请求消息,读应答
        if (socketChannel.connect(new InetSocketAddress(host, port))) {
            SelectionKey register = socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
        } else
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
    }

    public NetworkReceive getReceive() {
        return receive;
    }

    public void setReceive(NetworkReceive receive) {
        this.receive = receive;
    }

    public Send getSend() {
        return send;
    }

    public void setSend(Send send) {
        this.send = send;
    }
}

main函数

package org.apache.kafka.clients.producer;

import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.requests.MetadataRequest;
import org.apache.kafka.common.requests.RequestHeader;
import org.apache.kafka.common.requests.RequestSend;

public class QueryTopics {
    public static void main(String[] args) {
        // 1 建立连接 broker
        // 这里的 ip 和端口 要改为自己的
        TopicRequestHandle topicRequestHandle = new TopicRequestHandle("localhost", 9092);
        // 2 构建topic请求
        MetadataRequest request = MetadataRequest.allTopics();
        RequestHeader header = new RequestHeader(ApiKeys.METADATA.id, "", 0);
        RequestSend send = new RequestSend("-1",header, request.toStruct());
        // 3 发送请求
        topicRequestHandle.setSend(send);
        topicRequestHandle.run();
        // 4 得到数据
        Cluster cluster = topicRequestHandle.cluster;
        System.out.println(cluster);
    }
}

cluster就是生产者消费者api里,保存和集群topic有关的对象.

<think>好的,我现在需要帮助用户了解如何在Kafka中查看所有topic。首先,我得回想一下Kafka的相关命令,确保自己记得准确。记得kafka-topics.sh脚本是管理topic的主要工具,通常在Kafka安装目录的bin文件夹下。用户可能需要知道基本命令和参数,比如--list和--bootstrap-server。 然后,用户可能需要不同版本的命令,比如旧版本使用--zookeeper,而新版本用--bootstrap-server。这一点很重要,得区分清楚,避免用户混淆。同时,是否要详细说明参数的作用?比如解释--bootstrap-server后面跟的是Kafka服务器地址,端口默认9092,但实际中可能不同,需要提醒用户根据实际情况修改。 接下来,用户可能还想知道如何查看topic的详细信息,比如分区数、副本因子等。这时候需要补充使用--describe参数的例子,并解释输出结果的含义。比如分区信息、Leader节点、副本情况等,这些对用户排查问题有帮助。 还要考虑用户可能遇到的问题,比如环境变量未配置,导致无法直接运行kafka-topics.sh。这时候需要提示他们使用绝对路径,或者将脚本添加到PATH中。另外,如果用户没有正确设置--bootstrap-server的地址和端口,命令会失败,需要提醒检查配置。 有没有其他方式查看topic?比如使用Kafka的API或者管理工具,但用户可能更倾向于命令行,所以暂时不需要展开。不过可以提到图形化工具如Kafka Manager,作为备选方案。 需要检查命令的语法是否正确,比如在给出示例时,是否正确使用$$...$$和$...$格式?根据系统级指令,行内代码要用$...$,独立代码块用$$...$$并单独成段。例如,$./kafka-topics.sh --list --bootstrap-server localhost:9092$是否正确应用了格式。 还要注意使用中文回答,结构清晰,分步骤说明。可能需要分点列出不同情况,比如查看所有topic、查看详细信息、注意事项等。同时确保LaTeX语法正确,但在这里可能用不上太多数学公式,主要是在代码和参数上使用正确的格式。 总结一下,回答应该包括以下几个部分: 1. 使用kafka-topics.sh脚本的--list参数,分新旧版本说明不同的连接方式。 2. 示例命令,用正确的LaTeX格式标出。 3. 查看详细信息方法,使用--describe参数。 4. 注意事项,包括路径、服务器地址、端口等。 5. 可能提到的其他工具或方法。 最后,检查是否有遗漏,比如权限问题,或者Kafka服务是否正常运行,这些也会影响命令的执行,但用户可能已经知道,所以暂时作为注意事项简单提及即可。</think>在 Kafka 中查看所有 topic 的操作步骤如下: --- ### 1. **使用 `kafka-topics.sh` 工具** Kafka 提供了命令行工具 `kafka-topics.sh`(位于 Kafka 安装目录的 `bin/` 下),通过指定 `--list` 参数可列出所有 topic。 #### 命令格式: ```shell $$./kafka-topics.sh --list --bootstrap-server <broker地址>:<端口>$$ ``` #### 示例: ```shell $$./kafka-topics.sh --list --bootstrap-server localhost:9092$$ ``` --- ### 2. **旧版本 Kafka(依赖 ZooKeeper)** 如果使用 Kafka 旧版本(2.2 之前),需通过 `--zookeeper` 参数连接 ZooKeeper: ```shell $$./kafka-topics.sh --list --zookeeper localhost:2181$$ ``` --- ### 3. **查看 topic 详细信息** 若需查看 topic 的分区数、副本因子等详细信息,可使用 `--describe` 参数: ```shell $$./kafka-topics.sh --describe --bootstrap-server localhost:9092$$ ``` 输出示例: ``` $Topic: my-topic PartitionCount: 3 ReplicationFactor: 2$ $Topic: my-topic Partition: 0 Leader: 1 Replicas: 1,2 Isr: 1,2$ ``` --- ### 4. **注意事项** - **路径问题**:如果未配置环境变量,需使用绝对路径调用脚本,例如: ```shell $$/opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092$$ ``` - **服务器地址**:`--bootstrap-server` 需替换为实际 Kafka 服务器地址(如集群环境需指定多个地址,逗号分隔)。 - **端口检查**:默认端口为 `9092`,但需确认实际配置是否不同。 --- ### 5. **其他工具** - **Kafka Manager**:图形化管理工具,可直观查看 topic 列表及状态。 - **Kafka API**:通过编程方式(如 Java 客户端)调用 `AdminClient.listTopics()` 方法获取。 --- 通过以上步骤,可以快速查看 Kafka 中所有 topic 及其详细信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值