diff --git a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/ClusterBrokersManager.java b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/ClusterBrokersManager.java index 8427c1ef0..0eba136b1 100644 --- a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/ClusterBrokersManager.java +++ b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/ClusterBrokersManager.java @@ -17,6 +17,16 @@ public interface ClusterBrokersManager { */ PaginationResult getClusterPhyBrokersOverview(Long clusterPhyId, ClusterBrokersOverviewDTO dto); + /** + * 删除status == 0 的所有broker -> 获取缓存查询结果 & broker 表查询结果并集 + * 获取缓存查询结果 & broker 表查询结果并集 + * @param clusterPhyId kafka 物理集群 id + * @param dto 封装分页查询参数对象 + * @return 返回获取到的缓存查询结果 & broker 表查询结果并集 + */ + PaginationResult clearInactiveClusterPhyBrokers(Long clusterPhyId, ClusterBrokersOverviewDTO dto); + + /** * 根据物理集群id获取集群对应broker状态信息 * @param clusterPhyId 物理集群 id diff --git a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/impl/ClusterBrokersManagerImpl.java b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/impl/ClusterBrokersManagerImpl.java index c77724dd8..d8796dcdd 100644 --- a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/impl/ClusterBrokersManagerImpl.java +++ b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/cluster/impl/ClusterBrokersManagerImpl.java @@ -107,6 +107,12 @@ public PaginationResult getClusterPhyBrokersOverview(L ); } + @Override + public PaginationResult clearInactiveClusterPhyBrokers(Long clusterPhyId, ClusterBrokersOverviewDTO dto) { + brokerService.clearInactiveClusterPhyBrokers(clusterPhyId); + return this.getClusterPhyBrokersOverview(clusterPhyId, dto); + } + @Override public ClusterBrokersStateVO getClusterPhyBrokersState(Long clusterPhyId) { ClusterBrokersStateVO clusterBrokersStateVO = new ClusterBrokersStateVO(); diff --git a/km-console/packages/layout-clusters-fe/src/api/index.ts b/km-console/packages/layout-clusters-fe/src/api/index.ts index d07599524..97db801a0 100755 --- a/km-console/packages/layout-clusters-fe/src/api/index.ts +++ b/km-console/packages/layout-clusters-fe/src/api/index.ts @@ -120,6 +120,8 @@ const api = { getTopicMetricPoints: (clusterPhyId: number, topicName: string) => getApi(`/clusters/${clusterPhyId}/topics/${topicName}/metric-points`), // Broker列表接口 getBrokersList: (clusterPhyId: number) => getApi(`/clusters/${clusterPhyId}/brokers-overview`), + // 删除失效Broker + clearInactiveBrokers: (clusterPhyId: number) => getApi(`/clusters/${clusterPhyId}/brokers-clear`), // Broker列表页健康检查指标 getBrokerMetricPoints: (clusterPhyId: number) => getApi(`/physical-clusters/${clusterPhyId}/latest-metrics`), // Controller列表接口 /api/v3/clusters/{clusterPhyId}/controller-history「controller-change-log」 diff --git a/km-console/packages/layout-clusters-fe/src/constants/reg.ts b/km-console/packages/layout-clusters-fe/src/constants/reg.ts index 7463882a1..995ba2ccd 100644 --- a/km-console/packages/layout-clusters-fe/src/constants/reg.ts +++ b/km-console/packages/layout-clusters-fe/src/constants/reg.ts @@ -22,3 +22,5 @@ export const regTemplateName = /^[a-z0-9\._-]*$/; // 仅支持小写字母、数 export const regIp = /((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/g; // ip export const regKafkaPassword = /^[A-Za-z0-9_\-!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]*$/; + +export const regJmxPassword = /^[_a-zA-Z0-9-]*$/; // JMX密码:支持大小写字母、数字、下划线、短划线 diff --git a/km-console/packages/layout-clusters-fe/src/pages/BrokerList/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/BrokerList/index.tsx index 9d5dd0537..7d6402117 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/BrokerList/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/BrokerList/index.tsx @@ -66,6 +66,42 @@ const BrokerList: React.FC = (props: any) => { }); }; + // 请求接口获取数据 + const clearInactiveBrokers = async ({ pageNo, pageSize, filters, sorter }: any) => { + if (urlParams?.clusterId === undefined) return; + // filters = filters || filteredInfo; + setLoading(true); + const params = { + searchKeywords: searchKeywords.slice(0, 128), + pageNo, + pageSize, + latestMetricNames: ['PartitionsSkew', 'Leaders', 'LeadersSkew', 'LogSize'], + sortField: sorter?.field || 'brokerId', + sortType: sorter?.order ? sorter.order.substring(0, sorter.order.indexOf('end')) : 'asc', + }; + + request(API.clearInactiveBrokers(urlParams?.clusterId), { method: 'POST', data: params }) + .then((res: any) => { + setPagination({ + current: res.pagination?.pageNo, + pageSize: res.pagination?.pageSize, + total: res.pagination?.total, + }); + const newData = + res?.bizData.map((item: any) => { + return { + ...item, + ...item?.latestMetrics?.metrics, + }; + }) || []; + setData(newData); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + const onTableChange = (pagination: any, filters: any, sorter: any) => { // setFilteredInfo(filters); genData({ pageNo: pagination.current, pageSize: pagination.pageSize, filters, sorter }); @@ -107,6 +143,12 @@ const BrokerList: React.FC = (props: any) => { > +
clearInactiveBrokers({ pageNo: pagination.current, pageSize: pagination.pageSize })} + > + +
{ const originValue = obj?.jmxProperties; if (originValue) { const jmxProperties = JSON.parse(originValue); - typeof jmxProperties === 'object' && jmxProperties !== null && Object.assign(res, jmxProperties); + if (typeof jmxProperties === 'object' && jmxProperties !== null) { + Object.assign(res, jmxProperties); + // 根据是否有 username/token 判断是否启用密码认证 + const hasPasswordAuth = !!(jmxProperties.username && jmxProperties.token); + res.hasPasswordAuth = hasPasswordAuth; + // 如果没有密码认证,确保 openSSL 为 false + if (!hasPasswordAuth) { + res.openSSL = false; + } + } } } catch (err) { console.error('jmxProperties not JSON: ', err); @@ -257,8 +266,8 @@ const ClusterTabContent = forwardRef((props: any, ref): JSX.Element => { if (!value) { return Promise.reject('密码不能为空'); } - if (!new RegExp(regUsername).test(value)) { - return Promise.reject('密码只能由大小写、下划线、短划线(-)组成'); + if (!new RegExp(regJmxPassword).test(value)) { + return Promise.reject('密码只能由大小写字母、数字、下划线、短划线(-)组成'); } if (value.length < 6 || value.length > 32) { return Promise.reject('密码长度限制在6~32字符'); @@ -360,15 +369,15 @@ const ClusterTabContent = forwardRef((props: any, ref): JSX.Element => {
- + None Password Authentication - + {({ getFieldValue }) => { - return getFieldValue('openSSL') ? ( + return getFieldValue('hasPasswordAuth') ? (
@@ -379,6 +388,7 @@ const ClusterTabContent = forwardRef((props: any, ref): JSX.Element => { validator: validators.securityUserName, }, ]} + style={{ width: '140px', marginRight: '8px' }} > @@ -390,9 +400,13 @@ const ClusterTabContent = forwardRef((props: any, ref): JSX.Element => { validator: validators.securityToken, }, ]} + style={{ width: '140px', marginRight: '8px' }} > + + 启用 SSL +
) : null; @@ -759,9 +773,9 @@ const AccessClusterDrawer = (props: AccessClusterDrawerProps) => { jmxProperties: { jmxPort: res.jmxPort, maxConn: res.maxConn, - openSSL: res.openSSL || false, - token: res.token, - username: res.username, + openSSL: res.hasPasswordAuth ? (res.openSSL || false) : false, + token: res.hasPasswordAuth ? res.token : '', + username: res.hasPasswordAuth ? res.username : '', }, kafkaVersion: res.kafkaVersion, name: res.name, diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/BrokerService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/BrokerService.java index c8c300a0e..d690b0a6a 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/BrokerService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/BrokerService.java @@ -71,4 +71,6 @@ public interface BrokerService { boolean allServerDown(Long clusterPhyId); boolean existServerDown(Long clusterPhyId); + + void clearInactiveClusterPhyBrokers(Long clusterPhyId); } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/impl/BrokerServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/impl/BrokerServiceImpl.java index e34c035c5..105019f74 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/impl/BrokerServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/broker/impl/BrokerServiceImpl.java @@ -176,6 +176,20 @@ public List listNotAliveBrokersFromDB(Long clusterPhyId) { return this.listAllBrokersAndUpdateCache(clusterPhyId).stream().filter( elem -> !elem.alive()).collect(Collectors.toList()); } + /** + * 清理对应集群中下线的broker记录 + * @param clusterPhyId + */ + @Override + public void clearInactiveClusterPhyBrokers(Long clusterPhyId) { + try { + this.getAllBrokerPOsFromDB(clusterPhyId).stream() + .filter(elem -> elem.getStatus().equals(Constant.DOWN)) + .forEach(elem -> brokerDAO.deleteById(elem.getId())); + } catch (Exception e) { + log.error("method=clearInactiveClusterPhyBrokers||clusterPhyId={}||errMsg=exception!", clusterPhyId, e); + } + } @Override public List listAllBrokersFromDB(Long clusterPhyId) { return this.listAllBrokersAndUpdateCache(clusterPhyId); diff --git a/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/cluster/ClusterBrokersController.java b/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/cluster/ClusterBrokersController.java index db9c933a4..3bfe5c6ad 100644 --- a/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/cluster/ClusterBrokersController.java +++ b/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/cluster/ClusterBrokersController.java @@ -62,4 +62,12 @@ public PaginationResult getClusterPhyBrokersOverview(@ @RequestBody ClusterBrokersOverviewDTO dto) { return clusterBrokersManager.getClusterPhyBrokersOverview(clusterPhyId, dto); } + + @ApiOperation(value = "集群无效brokers清理") + @PostMapping(value = "clusters/{clusterPhyId}/brokers-clear") + @ResponseBody + public PaginationResult clearInactiveClusterPhyBrokers(@PathVariable Long clusterPhyId, + @RequestBody ClusterBrokersOverviewDTO dto) { + return clusterBrokersManager.clearInactiveClusterPhyBrokers(clusterPhyId, dto); + } } \ No newline at end of file