集群信息
This commit is contained in:
83
src/main/java/com/xuxd/kafka/console/beans/BrokerNode.java
Normal file
83
src/main/java/com/xuxd/kafka/console/beans/BrokerNode.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package com.xuxd.kafka.console.beans;
|
||||
|
||||
import org.apache.kafka.common.Node;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
*
|
||||
* @author xuxd
|
||||
* @date 2021-10-08 14:03:21
|
||||
**/
|
||||
public class BrokerNode {
|
||||
|
||||
private int id;
|
||||
|
||||
private String idString;
|
||||
|
||||
private String host;
|
||||
|
||||
private int port;
|
||||
|
||||
private String rack;
|
||||
|
||||
private boolean isController;
|
||||
|
||||
public static BrokerNode fromNode(Node node) {
|
||||
BrokerNode brokerNode = new BrokerNode();
|
||||
brokerNode.setId(node.id());
|
||||
brokerNode.setIdString(node.idString());
|
||||
brokerNode.setHost(node.host());
|
||||
brokerNode.setPort(node.port());
|
||||
brokerNode.setRack(node.rack());
|
||||
|
||||
return brokerNode;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getIdString() {
|
||||
return idString;
|
||||
}
|
||||
|
||||
public void setIdString(String idString) {
|
||||
this.idString = idString;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getRack() {
|
||||
return rack;
|
||||
}
|
||||
|
||||
public void setRack(String rack) {
|
||||
this.rack = rack;
|
||||
}
|
||||
|
||||
public boolean isController() {
|
||||
return isController;
|
||||
}
|
||||
|
||||
public void setController(boolean controller) {
|
||||
isController = controller;
|
||||
}
|
||||
}
|
||||
42
src/main/java/com/xuxd/kafka/console/beans/ClusterInfo.java
Normal file
42
src/main/java/com/xuxd/kafka/console/beans/ClusterInfo.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.xuxd.kafka.console.beans;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
*
|
||||
* @author xuxd
|
||||
* @date 2021-10-08 13:57:48
|
||||
**/
|
||||
public class ClusterInfo {
|
||||
|
||||
private Set<BrokerNode> nodes;
|
||||
|
||||
private Set<String> authorizedOperations;
|
||||
|
||||
private String clusterId;
|
||||
|
||||
public Set<BrokerNode> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public void setNodes(Set<BrokerNode> nodes) {
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public Set<String> getAuthorizedOperations() {
|
||||
return authorizedOperations;
|
||||
}
|
||||
|
||||
public void setAuthorizedOperations(Set<String> authorizedOperations) {
|
||||
this.authorizedOperations = authorizedOperations;
|
||||
}
|
||||
|
||||
public String getClusterId() {
|
||||
return clusterId;
|
||||
}
|
||||
|
||||
public void setClusterId(String clusterId) {
|
||||
this.clusterId = clusterId;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.xuxd.kafka.console.config;
|
||||
|
||||
import kafka.console.ClusterConsole;
|
||||
import kafka.console.ConsumerConsole;
|
||||
import kafka.console.KafkaAclConsole;
|
||||
import kafka.console.KafkaConfigConsole;
|
||||
@@ -35,4 +36,9 @@ public class KafkaConfiguration {
|
||||
public ConsumerConsole consumerConsole(KafkaConfig config) {
|
||||
return new ConsumerConsole(config);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClusterConsole clusterConsole(KafkaConfig config) {
|
||||
return new ClusterConsole(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xuxd.kafka.console.controller;
|
||||
|
||||
import com.xuxd.kafka.console.service.ClusterService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
*
|
||||
* @author xuxd
|
||||
* @date 2021-10-08 14:26:11
|
||||
**/
|
||||
@RestController
|
||||
@RequestMapping("/cluster")
|
||||
public class ClusterController {
|
||||
|
||||
@Autowired
|
||||
private ClusterService clusterService;
|
||||
|
||||
@GetMapping
|
||||
public Object getClusterInfo() {
|
||||
return clusterService.getClusterInfo();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xuxd.kafka.console.service;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
*
|
||||
* @author xuxd
|
||||
* @date 2021-10-08 14:22:30
|
||||
**/
|
||||
public interface ClusterService {
|
||||
ResponseData getClusterInfo();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.xuxd.kafka.console.service.impl;
|
||||
|
||||
import com.xuxd.kafka.console.beans.ResponseData;
|
||||
import com.xuxd.kafka.console.service.ClusterService;
|
||||
import kafka.console.ClusterConsole;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* kafka-console-ui.
|
||||
*
|
||||
* @author xuxd
|
||||
* @date 2021-10-08 14:23:09
|
||||
**/
|
||||
@Service
|
||||
public class ClusterServiceImpl implements ClusterService {
|
||||
|
||||
@Autowired
|
||||
private ClusterConsole clusterConsole;
|
||||
|
||||
@Override public ResponseData getClusterInfo() {
|
||||
return ResponseData.create().data(clusterConsole.clusterInfo()).success();
|
||||
}
|
||||
}
|
||||
44
src/main/scala/kafka/console/ClusterConsole.scala
Normal file
44
src/main/scala/kafka/console/ClusterConsole.scala
Normal file
@@ -0,0 +1,44 @@
|
||||
package kafka.console
|
||||
|
||||
import java.util.Collections
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import com.xuxd.kafka.console.beans.{BrokerNode, ClusterInfo}
|
||||
import com.xuxd.kafka.console.config.KafkaConfig
|
||||
import org.apache.kafka.clients.admin.DescribeClusterResult
|
||||
|
||||
import scala.jdk.CollectionConverters.{CollectionHasAsScala, SetHasAsJava, SetHasAsScala}
|
||||
|
||||
/**
|
||||
* kafka-console-ui. cluster console.
|
||||
*
|
||||
* @author xuxd
|
||||
* @date 2021-10-08 10:55:56
|
||||
* */
|
||||
class ClusterConsole(config: KafkaConfig) extends KafkaConsole(config: KafkaConfig) with Logging {
|
||||
|
||||
def clusterInfo(): ClusterInfo = {
|
||||
withAdminClientAndCatchError(admin => {
|
||||
val clusterResult: DescribeClusterResult = admin.describeCluster()
|
||||
val clusterInfo = new ClusterInfo
|
||||
clusterInfo.setClusterId(clusterResult.clusterId().get(3000, TimeUnit.MILLISECONDS))
|
||||
val acls = clusterResult.authorizedOperations().get(3000, TimeUnit.MILLISECONDS)
|
||||
if (acls != null) {
|
||||
clusterInfo.setAuthorizedOperations(acls.asScala.map(_.toString).toSet[String].asJava)
|
||||
} else {
|
||||
clusterInfo.setAuthorizedOperations(Collections.emptySet())
|
||||
}
|
||||
clusterInfo.setNodes(clusterResult.nodes().get(3000, TimeUnit.MILLISECONDS).asScala.map(BrokerNode.fromNode(_)).toSet[BrokerNode].asJava)
|
||||
val id = clusterResult.controller().get(3000, TimeUnit.MILLISECONDS).id()
|
||||
clusterInfo.getNodes.asScala.foreach(n => {
|
||||
if (n.getId == id) {
|
||||
n.setController(true)
|
||||
}
|
||||
})
|
||||
clusterInfo
|
||||
}, eh => {
|
||||
log.error("get clusterInfo error.", eh)
|
||||
new ClusterInfo
|
||||
}).asInstanceOf[ClusterInfo]
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
><router-link to="/acl-page" class="pad-l-r" v-show="config.enableAcl"
|
||||
>Acl</router-link
|
||||
>
|
||||
<span>|</span><router-link to="/op-page" class="pad-l-r">运维</router-link>
|
||||
<span>|</span
|
||||
><router-link to="/op-page" class="pad-l-r">运维</router-link>
|
||||
</div>
|
||||
<router-view class="content" />
|
||||
</div>
|
||||
|
||||
@@ -37,6 +37,12 @@ const routes = [
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "op" */ "../views/op/Operation.vue"),
|
||||
},
|
||||
{
|
||||
path: "/cluster-page",
|
||||
name: "Cluster",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "cluster" */ "../views/cluster/Cluster.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = new VueRouter({
|
||||
|
||||
@@ -85,3 +85,10 @@ export const KafkaConsumerApi = {
|
||||
method: "get",
|
||||
},
|
||||
};
|
||||
|
||||
export const KafkaClusterApi = {
|
||||
getClusterInfo: {
|
||||
url: "/cluster",
|
||||
method: "get",
|
||||
},
|
||||
};
|
||||
|
||||
92
ui/src/views/cluster/Cluster.vue
Normal file
92
ui/src/views/cluster/Cluster.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-spin :spinning="loading">
|
||||
<div class="body-c">
|
||||
<div class="cluster-id">
|
||||
<h3>集群ID:{{ clusterId }}</h3>
|
||||
</div>
|
||||
|
||||
<a-table :columns="columns" :data-source="data" bordered row-key="name">
|
||||
<div slot="addr" slot-scope="text, record">
|
||||
{{ record.host }}:{{ record.port }}
|
||||
</div>
|
||||
<div slot="controller" slot-scope="text">
|
||||
<span v-if="text" style="color: red">是</span><span v-else>否</span>
|
||||
</div>
|
||||
</a-table>
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import { KafkaClusterApi } from "@/utils/api";
|
||||
|
||||
export default {
|
||||
name: "Topic",
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
columns,
|
||||
loading: false,
|
||||
clusterId: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getClusterInfo() {
|
||||
this.loading = true;
|
||||
request({
|
||||
url: KafkaClusterApi.getClusterInfo.url,
|
||||
method: KafkaClusterApi.getClusterInfo.method,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
this.data = res.data.nodes;
|
||||
this.clusterId = res.data.clusterId;
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getClusterInfo();
|
||||
},
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "id",
|
||||
dataIndex: "id",
|
||||
key: "id",
|
||||
},
|
||||
{
|
||||
title: "地址",
|
||||
key: "addr",
|
||||
scopedSlots: { customRender: "addr" },
|
||||
},
|
||||
{
|
||||
title: "控制器",
|
||||
key: "controller",
|
||||
dataIndex: "controller",
|
||||
scopedSlots: { customRender: "controller" },
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.body-c {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cluster-id {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.operation-row-button {
|
||||
height: 4%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.operation-btn {
|
||||
margin-right: 3%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user