AdminClient
Apache提供的AdminClient中针对Topic的操作除了增删以外,自然还会有查询功能。本篇的主要内容是获取Topic列表,获取单个topic的详细信息等等。当然要完成Topic信息的查询,首先还是需要获取AdminClient,参考【Apache Kafka API AdminClient 获取对象】。更多内容请点击【Apache Kafka API AdminClient系列】。
获取Topic List
Kafka API中获取Topic List主要用到的方法是listTopics(),并且把结果封装为一个ListTopicsResult对象返回出去,而使用者使用的就是ListTopicsResult对象里面的各种方法去实现展示Topic各种信息。
ListTopicsResult
这个类中一共有三个不同级别的方法,用来输出Topic信息。那么就简单说下这个类中的三个主要方法:
- listings():返回一个
Collection<TopicListing>
对象,用来存放Topic信息。 - names():返回
Set<java.lang.String>
对象,用来Topic的名字。 - namesToListings():返回一个
Map<java.lang.String,TopicListing>
对象,内容和listings()相同,但是封装为map。
Sample
简单写一个方法就可以调用出来我们所需要的topic
列表。
public void topicLists() throws ExecutionException, InterruptedException {
ListTopicsResult result1 = adminClient.listTopics();
// 打印Topic的名称Set<String>
System.out.println(result1.names().get());
// 打印Topic列表的信息Map<String, TopicListing>>
System.out.println(result1.namesToListings().get());
// 打印Topic列表的信息Collection<TopicListing>>
System.out.println(result1.listings().get());
}
但是打印出来的结果大家一定会比较奇怪。以listings()
为例,打印的内容为:
topic1=(name=topic1, internal=false), topic2=(name=topic2, internal=false),......
所以这个internal
是个什么属性呢?这个是标识这个topic
是否是Kafka内部使用的。我们知道Kafka也会在使用过程中给自身创建一些topic
作为自己的配置topic
,比如说__consumer_offsets
,__transaction_state
等等。那么如果我们不需要显示这些,那么直接打印一般是没有的,怎么才能拿到呢?这里要介绍另一个参数ListTopicsOptions
去设置这个值,比如:
public void topicLists() throws ExecutionException, InterruptedException {
//初始化一个ListTopicsOptions对象
ListTopicsOptions options = new ListTopicsOptions();
// 是否列出kafka内部使用的Topic。true:列出;false:不列出。
options.listInternal(true);
//在拿到client的时候把参数传递进去
ListTopicsResult result2 = adminClient.listTopics(options);
//此时再打印就会发现(name=__transaction_state, internal=true)字样出现
System.out.println(result2.names().get());
System.out.println(result2.listings().get());
System.out.println(result2.namesToListings().get());
}
显示单个Topic的详细信息
AdminClient中也提供了一个方法可以拿到指定的Kafka信息describeTopics(java.util.Collection<java.lang.String> topicNames)
:
这里的参数是一个Collection的对象,方便使用来说一般都会只传递一个名字进去,当然特殊需求也可以传多个么,这里也简单举一个例子。传递出来的DescribeTopicsResult
而可以理解为一个Map,最终我们都是要通过Map去拿到具体的内容。
Sample
如下做了一个简单的封装,即可通过传入topic的名字,去拿到Topic的各种连接信息。这个方法不仅仅的拿到各种信息,还可以通过authorizedOperations()
方法给topic添加权限,不过这个等到详细介绍权限的地方再说。
public void describeTopicInfo(String topicName) throws ExecutionException, InterruptedException {
List<String> list = new ArrayList<String>();
list.add(topicName);
//调用方法拿到信息
DescribeTopicsResult topic = adminClient.describeTopics(list);
Map<String, TopicDescription> map = topic.all().get();
for (Map.Entry<String, TopicDescription> entry : map.entrySet()) {
System.out.println("topicName:" + entry.getValue().name()); //当前topic的名字
System.out.println("partition num:" + entry.getValue().partitions().size()); //当前topic的partition数量
System.out.println("listp:");
List<TopicPartitionInfo> listp = entry.getValue().partitions(); //拿到topic的partitions相关信息
for (TopicPartitionInfo info : listp) {
System.out.println("----------------------------------");
System.out.println("info.partition():" + info.partition());
System.out.println("info.leader().id():" + info.leader().id()); //领导者所在机器id,也就是机器编号配置文件中的service id
System.out.println("info.leader().host():" + info.leader().host()); //领导者所在机器host ip
System.out.println("info.leader().port():" + info.leader().port()); //领导者所在机器port
System.out.println("info.replicas():" + info.replicas()); //副本的信息,有多少会拿到多少
List<Node> listInfo = info.replicas();
//输出node信息
for (Node n : listInfo) {
System.out.println("info.id():" + n.id()); //副本所在的node id
System.out.println("info.host():" + n.host()); //副本所在node的host ip
System.out.println("info.port():" + n.port()); //副本所在node的port
}
}
}
}