From 90e54920608b1711d732582fdcd8b45e15d829e7 Mon Sep 17 00:00:00 2001 From: EricZeng Date: Tue, 18 Jul 2023 14:25:26 +0800 Subject: [PATCH 01/48] =?UTF-8?q?[Bugfix]=E5=A2=9E=E5=8A=A0=E6=9F=A5?= =?UTF-8?q?=E7=9C=8BUser=E5=AF=86=E7=A0=81=E7=9A=84=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=82=B9=20(#1095)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仅后端增加,前端相关代码暂未补充 --- ...4\254\345\215\207\347\272\247\346\211\213\345\206\214.md" | 5 +++++ km-persistence/src/main/resources/sql/dml-logi.sql | 4 ++++ 2 files changed, 9 insertions(+) diff --git "a/docs/install_guide/\347\211\210\346\234\254\345\215\207\347\272\247\346\211\213\345\206\214.md" "b/docs/install_guide/\347\211\210\346\234\254\345\215\207\347\272\247\346\211\213\345\206\214.md" index 675a9dabd..5763026d1 100644 --- "a/docs/install_guide/\347\211\210\346\234\254\345\215\207\347\272\247\346\211\213\345\206\214.md" +++ "b/docs/install_guide/\347\211\210\346\234\254\345\215\207\347\272\247\346\211\213\345\206\214.md" @@ -53,6 +53,11 @@ INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `l INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2046', '0', 'know-streaming'); INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2048', '0', 'know-streaming'); INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2050', '0', 'know-streaming'); + + +-- 多集群管理权限2023-07-18新增 +INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2052', 'Security-User查看密码', '1593', '1', '2', 'Security-User查看密码', '0', 'know-streaming'); +INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2052', '0', 'know-streaming'); ``` ### 升级至 `3.3.0` 版本 diff --git a/km-persistence/src/main/resources/sql/dml-logi.sql b/km-persistence/src/main/resources/sql/dml-logi.sql index 2beff22e1..be171d5f3 100644 --- a/km-persistence/src/main/resources/sql/dml-logi.sql +++ b/km-persistence/src/main/resources/sql/dml-logi.sql @@ -157,3 +157,7 @@ INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `l INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2046', '0', 'know-streaming'); INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2048', '0', 'know-streaming'); INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2050', '0', 'know-streaming'); + +-- 多集群管理权限2023-07-18新增 +INSERT INTO `logi_security_permission` (`id`, `permission_name`, `parent_id`, `leaf`, `level`, `description`, `is_delete`, `app_name`) VALUES ('2052', 'Security-User查看密码', '1593', '1', '2', 'Security-User查看密码', '0', 'know-streaming'); +INSERT INTO `logi_security_role_permission` (`role_id`, `permission_id`, `is_delete`, `app_name`) VALUES ('1677', '2052', '0', 'know-streaming'); From b1892c21e2ff38b56a431f3a76fc4b3a60b0a741 Mon Sep 17 00:00:00 2001 From: lucasun Date: Tue, 1 Aug 2023 16:34:30 +0800 Subject: [PATCH 02/48] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2=E5=A4=B1=E8=B4=A5=E7=AD=89?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20(#1107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.新增角色不选择系统管理权限点报错问题; 2.Connect配置项里面涉及敏感字段的值用*号代替; 3.Topic详情、ConsumerGroup详情,ConsumerGroup表格支持手动刷; 4.Topic Message预览,Offset为0不显示数值,添加offset排序; --------- Co-authored-by: 孙超 Co-authored-by: EricZeng --- .../src/pages/UserManage/RoleTabContent.tsx | 4 +- .../layout-clusters-fe/config/webpack.dev.js | 4 +- .../src/components/utils.ts | 10 ++++ .../src/pages/Connect/AddConnector.tsx | 2 + .../src/pages/ConsumerGroup/Detail.tsx | 14 ++++- .../src/pages/SecurityACLs/EditDrawer.tsx | 58 +++++++++++++++++++ .../src/pages/TopicDetail/BrokersDetail.tsx | 10 +++- .../src/pages/TopicDetail/config.tsx | 3 +- .../src/pages/TopicDetail/index.less | 1 + .../src/pages/TopicDetail/index.tsx | 42 +++++++++----- 10 files changed, 127 insertions(+), 21 deletions(-) create mode 100644 km-console/packages/layout-clusters-fe/src/components/utils.ts diff --git a/km-console/packages/config-manager-fe/src/pages/UserManage/RoleTabContent.tsx b/km-console/packages/config-manager-fe/src/pages/UserManage/RoleTabContent.tsx index eb0b82e9a..d50c77cfd 100644 --- a/km-console/packages/config-manager-fe/src/pages/UserManage/RoleTabContent.tsx +++ b/km-console/packages/config-manager-fe/src/pages/UserManage/RoleTabContent.tsx @@ -96,7 +96,7 @@ const RoleDetailAndUpdate = forwardRef((props, ref): JSX.Element => { arr.push(permissions[i].id); } }); - formData.permissionIdList = formData.permissionIdList.flat(); + formData.permissionIdList = formData.permissionIdList.flat().filter((item) => item !== undefined); setConfirmLoading(true); request(api.editRole, { method: type === RoleOperate.Add ? 'POST' : 'PUT', @@ -250,7 +250,7 @@ const RoleDetailAndUpdate = forwardRef((props, ref): JSX.Element => { (0); + const forceRefresh: () => void = useCallback(() => { + setRefresh((x) => x + 1); + }, []); + + return [refreshKey, forceRefresh]; +} diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx index 8724a0291..ef6a55bdf 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx @@ -816,6 +816,8 @@ const StepFormFifth = (props: SubFormProps) => { ) : type.toUpperCase() === 'BOOLEAN' ? ( + ) : type.toUpperCase() === 'PASSWORD' ? ( + ) : ( )} diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx index 34001fa03..f01bee14d 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx @@ -1,12 +1,13 @@ import React, { useState, useEffect } from 'react'; import { useParams, useHistory } from 'react-router-dom'; -import { Drawer, ProTable, Utils } from 'knowdesign'; +import { Button, Space, Divider, Drawer, ProTable, Utils } from 'knowdesign'; import { IconFont } from '@knowdesign/icons'; import API from '@src/api/index'; import { defaultPagination, hashDataParse } from '@src/constants/common'; import { getGtoupTopicColumns } from './config'; import { ExpandedRow } from './ExpandedRow'; import ResetOffsetDrawer from './ResetOffsetDrawer'; +import { useForceRefresh } from '@src/components/utils'; const { request } = Utils; export interface MetricLine { @@ -63,6 +64,7 @@ const GroupDetail = (props: any) => { const [openKeys, setOpenKeys] = useState(); const [resetOffsetVisible, setResetOffsetVisible] = useState(false); const [resetOffsetArg, setResetOffsetArg] = useState({}); + const [refreshKey, forceRefresh] = useForceRefresh(); const genData = async ({ pageNo, pageSize, groupName }: any) => { if (urlParams?.clusterId === undefined) return; @@ -160,7 +162,7 @@ const GroupDetail = (props: any) => { // // 获取Consumer列表 表格模式 // getTopicGroupMetric(hashData); // }); - }, [hashDataParse(location.hash).groupName]); + }, [hashDataParse(location.hash).groupName, refreshKey]); return ( { // // // } + extra={ + + void}> + + + + + } > { if (configType === 'custom') { // 1. 自定义权限 + // TODO: 需要和后端联调 const { resourceType, resourcePatternType, aclPermissionType, aclOperation, aclClientHost } = formData; submitData.push({ clusterId, @@ -281,6 +282,42 @@ const AddDrawer = forwardRef((_, ref) => { {({ getFieldValue }) => { + const SelectFormItems = (props: { type: string }) => { + const { type } = props; + return ( + ({ + validator: (rule: any, value: string) => { + if (!value) { + return Promise.reject(`${type}Name 不能为空`); + } + if (type === 'topic' && getFieldValue(`${type}PatternType`) === ACL_PATTERN_TYPE['Literal']) { + return Utils.request(api.getTopicMetadata(clusterId as any, value)).then((res: any) => { + return res?.exist ? Promise.resolve() : Promise.reject('该 Topic 不存在'); + }); + } + return Promise.resolve(); + }, + }), + ]} + > + { + if (option?.value.includes(value)) { + return true; + } + return false; + }} + options={type === 'topic' ? topicMetaData : groupMetaData} + placeholder={`请输入 ${type}Name`} + /> + + ); + }; const PatternTypeFormItems = (props: { type: string }) => { const { type } = props; const UpperCaseType = type[0].toUpperCase() + type.slice(1); @@ -388,6 +425,27 @@ const AddDrawer = forwardRef((_, ref) => { }))} /> + + {({ getFieldValue }) => { + const type = getFieldValue('resourceType'); + if (type === ACL_RESOURCE_TYPE['Cluster'] || type === ACL_RESOURCE_TYPE['TransactionalId']) { + //TODO需要和后端获取集群和事务接口联调 + return ( + + + + ); + } else if (type === ACL_RESOURCE_TYPE['Topic']) { + return ; + } else if (type === ACL_RESOURCE_TYPE['Group']) { + return ; + } + return null; + }} + {({ getFieldValue }) => { form.resetFields(['aclOperation']); diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/BrokersDetail.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/BrokersDetail.tsx index 9b3a12a09..f2bb1713b 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/BrokersDetail.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/BrokersDetail.tsx @@ -8,6 +8,7 @@ import { useParams } from 'react-router-dom'; import TagsWithHide from '@src/components/TagsWithHide'; import SwitchTab from '@src/components/SwitchTab'; import RenderEmpty from '@src/components/RenderEmpty'; +import { useForceRefresh } from '@src/components/utils'; interface PropsType { hashData: any; @@ -401,11 +402,18 @@ export default (props: PropsType) => { const { hashData } = props; const [showMode, setShowMode] = useState('card'); + const [refreshKey, forceRefresh] = useForceRefresh(); return ( <> -
+
+ void} + > + +
diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx index aa1e25d3e..a6cdbc251 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx @@ -81,7 +81,8 @@ export const getTopicMessagesColmns = () => { title: 'Offset', dataIndex: 'offset', key: 'offset', - render: (t: number) => (t ? t.toLocaleString() : '-'), + sorter: true, + render: (t: number) => (+t ? t.toLocaleString() : '-'), }, { title: 'Timestamp', diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.less b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.less index f13249ab0..ea8470f81 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.less +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.less @@ -26,6 +26,7 @@ .left { display: flex; + align-items: center; .info-box { display: flex; height: 36px; diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.tsx index ea009bd44..169f81769 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/index.tsx @@ -15,9 +15,21 @@ import Replicator from './Replicator'; import './index.less'; import TopicDetailHealthCheck from '@src/components/CardBar/TopicDetailHealthCheck'; import { hashDataParse } from '@src/constants/common'; +import { useForceRefresh } from '@src/components/utils'; const { TabPane } = Tabs; +const Reload = (props: any) => { + return ( + void} + > + + + ); +}; + const OperationsSlot: any = { // eslint-disable-next-line react/display-name // ['Partitions']: (arg: any) => { @@ -70,17 +82,20 @@ const OperationsSlot: any = { // eslint-disable-next-line react/display-name ['ConsumerGroups']: (arg: any) => { return ( - + <> + + + ); }, }; @@ -94,6 +109,7 @@ const TopicDetail = (props: any) => { const [searchValue, setSearchValue] = useState(''); const [visible, setVisible] = useState(false); const [hashData, setHashData] = useState({}); + const [refreshKey, forceRefresh] = useForceRefresh(); const callback = (key: any) => { setSearchValue(''); @@ -184,7 +200,7 @@ const TopicDetail = (props: any) => { onChange={callback} tabBarExtraContent={ OperationsSlot[positionType] && - OperationsSlot[positionType]({ ...props, setSearchKeywords, setSearchValue, searchValue, positionType }) + OperationsSlot[positionType]({ ...props, setSearchKeywords, setSearchValue, searchValue, positionType, forceRefresh }) } destroyInactiveTabPane > @@ -196,7 +212,7 @@ const TopicDetail = (props: any) => { {positionType === 'ConsumerGroups' && ( - + )} From bdffc10ca6570158389a06c076d552d34278d586 Mon Sep 17 00:00:00 2001 From: chang-wd <51365967+chang-wd@users.noreply.github.com> Date: Wed, 2 Aug 2023 12:15:40 +0800 Subject: [PATCH 03/48] =?UTF-8?q?[Bugfix]=E4=BF=AE=E5=A4=8DLdap=20user.get?= =?UTF-8?q?Id()=20NPE=E9=97=AE=E9=A2=98=20(#1108)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NPE solved Co-authored-by: weidong_chang --- .../streaming/km/account/login/ldap/LdapLoginServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java b/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java index 3c0833e55..64dc78ad9 100644 --- a/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java +++ b/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java @@ -79,7 +79,7 @@ public UserBriefVO verifyLogin(AccountLoginDTO loginDTO, userService.addUser(userDTO, ldapAttrsInfo.getSAMAccountName()); // user赋值 - user = ConvertUtil.obj2Obj(userDTO, User.class); + user = userService.getUserByUserName(ldapAttrsInfo.getSAMAccountName()); } // 记录登录状态 From 55161e439a418ea8dbc185efe29a6acf4453f59b Mon Sep 17 00:00:00 2001 From: EricZeng Date: Wed, 2 Aug 2023 21:07:45 +0800 Subject: [PATCH 04/48] =?UTF-8?q?[Optimize]=E5=A2=9E=E5=8A=A0Connector?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E7=8A=B6=E6=80=81=E6=8C=87=E6=A0=87=20(#1110?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、增加Connector运行状态指标; 2、将Connector指标上报普罗米修斯; 3、调整代码继承关系; --- .../connect/ConnectClusterMetrics.java | 13 ++-- .../metrics/connect/ConnectWorkerMetrics.java | 20 ++---- .../metrics/connect/ConnectorMetrics.java | 18 ++--- .../metrics/connect/ConnectorTaskMetrics.java | 16 ++--- .../enums/connect/ConnectStatusEnum.java | 50 ++++++++++++++ .../impl/ConnectClusterMetricServiceImpl.java | 16 ++--- .../impl/ConnectorMetricServiceImpl.java | 65 +++++++++++-------- .../impl/MirrorMakerMetricServiceImpl.java | 6 +- ...ice.java => BaseConnectMetricService.java} | 2 +- ... => BaseConnectVersionControlService.java} | 2 +- .../connect/ConnectorMetricVersionItems.java | 5 ++ .../km/monitor/common/MonitorSinkTagEnum.java | 5 ++ .../component/AbstractMonitorSinkService.java | 21 ++++++ .../ConnectClusterMetricESDAO.java | 2 +- 14 files changed, 156 insertions(+), 85 deletions(-) create mode 100644 km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/enums/connect/ConnectStatusEnum.java rename km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/{BaseConnectorMetricService.java => BaseConnectMetricService.java} (90%) rename km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/{BaseConnectorVersionControlService.java => BaseConnectVersionControlService.java} (95%) rename km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/{ => cluster}/ConnectClusterMetricESDAO.java (99%) diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectClusterMetrics.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectClusterMetrics.java index fe710391e..f7c508187 100644 --- a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectClusterMetrics.java +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectClusterMetrics.java @@ -1,7 +1,6 @@ package com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.connect; import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.BaseMetrics; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @@ -12,20 +11,18 @@ */ @Data @NoArgsConstructor -@AllArgsConstructor @ToString public class ConnectClusterMetrics extends BaseMetrics { - private Long connectClusterId; + protected Long connectClusterId; - public ConnectClusterMetrics(Long clusterPhyId, Long connectClusterId){ + public ConnectClusterMetrics(Long clusterPhyId, Long connectClusterId ){ super(clusterPhyId); this.connectClusterId = connectClusterId; } - public static ConnectClusterMetrics initWithMetric(Long connectClusterId, String metric, Float value) { - ConnectClusterMetrics brokerMetrics = new ConnectClusterMetrics(connectClusterId, connectClusterId); - brokerMetrics.putMetric(metric, value); - return brokerMetrics; + public ConnectClusterMetrics(Long connectClusterId, String metricName, Float metricValue) { + this(null, connectClusterId); + this.putMetric(metricName, metricValue); } @Override diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectWorkerMetrics.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectWorkerMetrics.java index 78d9fe063..de4936e56 100644 --- a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectWorkerMetrics.java +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectWorkerMetrics.java @@ -1,7 +1,5 @@ package com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.connect; -import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.BaseMetrics; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @@ -11,25 +9,19 @@ * @date 2022/11/2 */ @Data -@AllArgsConstructor @NoArgsConstructor @ToString -public class ConnectWorkerMetrics extends BaseMetrics { - - private Long connectClusterId; - +public class ConnectWorkerMetrics extends ConnectClusterMetrics { private String workerId; - public static ConnectWorkerMetrics initWithMetric(Long connectClusterId, String workerId, String metric, Float value) { - ConnectWorkerMetrics connectWorkerMetrics = new ConnectWorkerMetrics(); - connectWorkerMetrics.setConnectClusterId(connectClusterId); - connectWorkerMetrics.setWorkerId(workerId); - connectWorkerMetrics.putMetric(metric, value); - return connectWorkerMetrics; + public ConnectWorkerMetrics(Long connectClusterId, String workerId, String metricName, Float metricValue) { + super(null, connectClusterId); + this.workerId = workerId; + this.putMetric(metricName, metricValue); } @Override public String unique() { - return "KCC@" + clusterPhyId + "@" + connectClusterId + "@" + workerId; + return "KCW@" + clusterPhyId + "@" + connectClusterId + "@" + workerId; } } diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorMetrics.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorMetrics.java index 08540ed5b..b497efb87 100644 --- a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorMetrics.java +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorMetrics.java @@ -1,6 +1,5 @@ package com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.connect; -import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.BaseMetrics; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @@ -12,24 +11,21 @@ @Data @NoArgsConstructor @ToString -public class ConnectorMetrics extends BaseMetrics { - private Long connectClusterId; +public class ConnectorMetrics extends ConnectClusterMetrics { + protected String connectorName; - private String connectorName; - - private String connectorNameAndClusterId; + protected String connectorNameAndClusterId; public ConnectorMetrics(Long connectClusterId, String connectorName) { - super(null); + super(null, connectClusterId); this.connectClusterId = connectClusterId; this.connectorName = connectorName; this.connectorNameAndClusterId = connectorName + "#" + connectClusterId; } - public static ConnectorMetrics initWithMetric(Long connectClusterId, String connectorName, String metricName, Float value) { - ConnectorMetrics metrics = new ConnectorMetrics(connectClusterId, connectorName); - metrics.putMetric(metricName, value); - return metrics; + public ConnectorMetrics(Long connectClusterId, String connectorName, String metricName, Float metricValue) { + this(connectClusterId, connectorName); + this.putMetric(metricName, metricValue); } @Override diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorTaskMetrics.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorTaskMetrics.java index eb0dc42de..fc28c97e9 100644 --- a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorTaskMetrics.java +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/metrics/connect/ConnectorTaskMetrics.java @@ -1,6 +1,5 @@ package com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.connect; -import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.BaseMetrics; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @@ -12,11 +11,7 @@ @Data @NoArgsConstructor @ToString -public class ConnectorTaskMetrics extends BaseMetrics { - private Long connectClusterId; - - private String connectorName; - +public class ConnectorTaskMetrics extends ConnectorMetrics { private Integer taskId; public ConnectorTaskMetrics(Long connectClusterId, String connectorName, Integer taskId) { @@ -25,14 +20,13 @@ public ConnectorTaskMetrics(Long connectClusterId, String connectorName, Integer this.taskId = taskId; } - public static ConnectorTaskMetrics initWithMetric(Long connectClusterId, String connectorName, Integer taskId, String metricName, Float value) { - ConnectorTaskMetrics metrics = new ConnectorTaskMetrics(connectClusterId, connectorName, taskId); - metrics.putMetric(metricName,value); - return metrics; + public ConnectorTaskMetrics(Long connectClusterId, String connectorName, Integer taskId, String metricName, Float metricValue) { + this(connectClusterId, connectorName, taskId); + this.putMetric(metricName, metricValue); } @Override public String unique() { - return "KCOR@" + connectClusterId + "@" + connectorName + "@" + taskId; + return "KCORT@" + connectClusterId + "@" + connectorName + "@" + taskId; } } diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/enums/connect/ConnectStatusEnum.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/enums/connect/ConnectStatusEnum.java new file mode 100644 index 000000000..235cead61 --- /dev/null +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/enums/connect/ConnectStatusEnum.java @@ -0,0 +1,50 @@ +package com.xiaojukeji.know.streaming.km.common.enums.connect; + +import org.apache.kafka.connect.runtime.AbstractStatus; + +/** + * connector运行状态 + * @see AbstractStatus + */ +public enum ConnectStatusEnum { + UNASSIGNED(0, "UNASSIGNED"), + + RUNNING(1,"RUNNING"), + + PAUSED(2,"PAUSED"), + + FAILED(3, "FAILED"), + + DESTROYED(4, "DESTROYED"), + + UNKNOWN(-1, "UNKNOWN") + + ; + + ConnectStatusEnum(int status, String value) { + this.status = status; + this.value = value; + } + + private final int status; + + private final String value; + + public static ConnectStatusEnum getByValue(String value) { + for (ConnectStatusEnum statusEnum: ConnectStatusEnum.values()) { + if (statusEnum.value.equals(value)) { + return statusEnum; + } + } + + return ConnectStatusEnum.UNKNOWN; + } + + public int getStatus() { + return status; + } + + public String getValue() { + return value; + } +} diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterMetricServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterMetricServiceImpl.java index 5ed5af645..1444d3ac1 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterMetricServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterMetricServiceImpl.java @@ -24,9 +24,9 @@ import com.xiaojukeji.know.streaming.km.core.service.connect.cluster.ConnectClusterMetricService; import com.xiaojukeji.know.streaming.km.core.service.connect.cluster.ConnectClusterService; import com.xiaojukeji.know.streaming.km.core.service.connect.worker.WorkerService; -import com.xiaojukeji.know.streaming.km.core.service.version.BaseConnectorMetricService; +import com.xiaojukeji.know.streaming.km.core.service.version.BaseConnectMetricService; import com.xiaojukeji.know.streaming.km.persistence.connect.ConnectJMXClient; -import com.xiaojukeji.know.streaming.km.persistence.es.dao.connect.ConnectClusterMetricESDAO; +import com.xiaojukeji.know.streaming.km.persistence.es.dao.connect.cluster.ConnectClusterMetricESDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -43,7 +43,7 @@ * @author didi */ @Service -public class ConnectClusterMetricServiceImpl extends BaseConnectorMetricService implements ConnectClusterMetricService { +public class ConnectClusterMetricServiceImpl extends BaseConnectMetricService implements ConnectClusterMetricService { protected static final ILog LOGGER = LogFactory.getLog(ConnectClusterMetricServiceImpl.class); public static final String CONNECT_CLUSTER_METHOD_GET_WORKER_METRIC_AVG = "getWorkerMetricAvg"; @@ -86,8 +86,7 @@ public Result collectConnectClusterMetricsFromKafkaWithCa String connectClusterMetricKey = CollectedMetricsLocalCache.genConnectClusterMetricCacheKey(connectClusterPhyId, metric); Float keyValue = CollectedMetricsLocalCache.getConnectClusterMetrics(connectClusterMetricKey); if (keyValue != null) { - ConnectClusterMetrics connectClusterMetrics = ConnectClusterMetrics.initWithMetric(connectClusterPhyId,metric,keyValue); - return Result.buildSuc(connectClusterMetrics); + return Result.buildSuc(new ConnectClusterMetrics(connectClusterPhyId, metric, keyValue)); } Result ret = this.collectConnectClusterMetricsFromKafka(connectClusterPhyId, metric); @@ -209,8 +208,7 @@ private Result getConnectWorkerMetricByJMX(Long connectClu try { //2、获取jmx指标 String value = jmxConnectorWrap.getAttribute(new ObjectName(jmxInfo.getJmxObjectName()), jmxInfo.getJmxAttribute()).toString(); - ConnectWorkerMetrics connectWorkerMetrics = ConnectWorkerMetrics.initWithMetric(connectClusterId, workerId, metric, Float.valueOf(value)); - return Result.buildSuc(connectWorkerMetrics); + return Result.buildSuc(new ConnectWorkerMetrics(connectClusterId, workerId, metric, Float.valueOf(value))); } catch (Exception e) { LOGGER.error("method=getConnectWorkerMetricsByJMX||connectClusterId={}||workerId={}||metrics={}||jmx={}||msg={}", connectClusterId, workerId, metric, jmxInfo.getJmxObjectName(), e.getClass().getName()); @@ -231,8 +229,8 @@ private List listTopNConnectClusterIdList(Long clusterPhyId, Integer topN) .collect(Collectors.toList()); } - protected List metricMap2VO(Long connectClusterId, - Map>> map){ + private List metricMap2VO(Long connectClusterId, + Map>> map){ List multiLinesVOS = new ArrayList<>(); if (map == null || map.isEmpty()) { // 如果为空,则直接返回 diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorMetricServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorMetricServiceImpl.java index 8792875d3..ffcc16ab4 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorMetricServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorMetricServiceImpl.java @@ -18,6 +18,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.vo.metrics.line.MetricLineVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.metrics.line.MetricMultiLinesVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.metrics.point.MetricPointVO; +import com.xiaojukeji.know.streaming.km.common.enums.connect.ConnectStatusEnum; import com.xiaojukeji.know.streaming.km.common.enums.connect.ConnectorTypeEnum; import com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum; import com.xiaojukeji.know.streaming.km.common.exception.VCHandlerNotExistException; @@ -32,7 +33,7 @@ import com.xiaojukeji.know.streaming.km.core.service.connect.worker.WorkerConnectorService; import com.xiaojukeji.know.streaming.km.core.service.connect.worker.WorkerService; import com.xiaojukeji.know.streaming.km.core.service.health.state.HealthStateService; -import com.xiaojukeji.know.streaming.km.core.service.version.BaseConnectorMetricService; +import com.xiaojukeji.know.streaming.km.core.service.version.BaseConnectMetricService; import com.xiaojukeji.know.streaming.km.persistence.connect.ConnectJMXClient; import com.xiaojukeji.know.streaming.km.persistence.es.dao.connect.connector.ConnectorMetricESDAO; import org.springframework.beans.factory.annotation.Autowired; @@ -52,7 +53,7 @@ * @author didi */ @Service -public class ConnectorMetricServiceImpl extends BaseConnectorMetricService implements ConnectorMetricService { +public class ConnectorMetricServiceImpl extends BaseConnectMetricService implements ConnectorMetricService { protected static final ILog LOGGER = LogFactory.getLog(ConnectorMetricServiceImpl.class); public static final String CONNECTOR_METHOD_DO_NOTHING = "doNothing"; @@ -67,6 +68,8 @@ public class ConnectorMetricServiceImpl extends BaseConnectorMetricService imple public static final String CONNECTOR_METHOD_GET_METRIC_HEALTH_SCORE = "getMetricHealthScore"; + public static final String CONNECTOR_METHOD_GET_METRIC_RUNNING_STATUS = "getMetricRunningStatus"; + @Autowired private ConnectorMetricESDAO connectorMetricESDAO; @@ -98,11 +101,12 @@ protected List listMetricPOFields() { @Override protected void initRegisterVCHandler() { registerVCHandler(CONNECTOR_METHOD_DO_NOTHING, this::doNothing); - registerVCHandler(CONNECTOR_METHOD_GET_CONNECT_WORKER_METRIC_SUM, this::getConnectWorkerMetricSum); - registerVCHandler(CONNECTOR_METHOD_GET_CONNECTOR_TASK_METRICS_AVG, this::getConnectorTaskMetricsAvg); - registerVCHandler(CONNECTOR_METHOD_GET_CONNECTOR_TASK_METRICS_MAX, this::getConnectorTaskMetricsMax); - registerVCHandler(CONNECTOR_METHOD_GET_CONNECTOR_TASK_METRICS_SUM, this::getConnectorTaskMetricsSum); - registerVCHandler(CONNECTOR_METHOD_GET_METRIC_HEALTH_SCORE, this::getMetricHealthScore); + registerVCHandler(CONNECTOR_METHOD_GET_CONNECT_WORKER_METRIC_SUM, this::getConnectWorkerMetricSum); + registerVCHandler(CONNECTOR_METHOD_GET_CONNECTOR_TASK_METRICS_AVG, this::getConnectorTaskMetricsAvg); + registerVCHandler(CONNECTOR_METHOD_GET_CONNECTOR_TASK_METRICS_MAX, this::getConnectorTaskMetricsMax); + registerVCHandler(CONNECTOR_METHOD_GET_CONNECTOR_TASK_METRICS_SUM, this::getConnectorTaskMetricsSum); + registerVCHandler(CONNECTOR_METHOD_GET_METRIC_HEALTH_SCORE, this::getMetricHealthScore); + registerVCHandler(CONNECTOR_METHOD_GET_METRIC_RUNNING_STATUS, this::getMetricRunningStatus); } @Override @@ -111,8 +115,7 @@ public Result collectConnectClusterMetricsFromKafkaWithCacheFi Float keyValue = CollectedMetricsLocalCache.getConnectorMetrics(connectorMetricKey); if (null != keyValue) { - ConnectorMetrics connectorMetrics = ConnectorMetrics.initWithMetric(connectClusterPhyId, connectorName, metric, keyValue); - return Result.buildSuc(connectorMetrics); + return Result.buildSuc(new ConnectorMetrics(connectClusterPhyId, connectorName, metric, keyValue)); } Result ret = this.collectConnectClusterMetricsFromKafka(connectClusterPhyId, connectorName, metric); @@ -216,6 +219,20 @@ private Result getMetricHealthScore(VersionItemParam metricPar return Result.buildSuc(metrics); } + private Result getMetricRunningStatus(VersionItemParam metricParam) { + ConnectorMetricParam param = (ConnectorMetricParam) metricParam; + Long connectClusterId = param.getConnectClusterId(); + String connectorName = param.getConnectorName(); + String metricName = param.getMetricName(); + + ConnectorPO connector = connectorService.getConnectorFromDB(connectClusterId, connectorName); + if (connector == null) { + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metricName, (float)ConnectStatusEnum.UNKNOWN.getStatus())); + } + + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metricName, (float)ConnectStatusEnum.getByValue(connector.getState()).getStatus())); + } + private Result getConnectWorkerMetricSum(VersionItemParam metricParam) { ConnectorMetricParam param = (ConnectorMetricParam) metricParam; Long connectClusterId = param.getConnectClusterId(); @@ -240,12 +257,16 @@ private Result getConnectWorkerMetricSum(VersionItemParam metr if (!isCollected) { return Result.buildFailure(NOT_EXIST); } - return Result.buildSuc(ConnectorMetrics.initWithMetric(connectClusterId, connectorName, metric, sum)); + + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metric, sum)); } //kafka.connect:type=connect-worker-metrics,connector="{connector}" 指标 private Result getConnectorMetric(Long connectClusterId, String workerId, String connectorName, String metric, ConnectorTypeEnum connectorType) { VersionConnectJmxInfo jmxInfo = getJMXInfo(connectClusterId, metric); + if (null == jmxInfo) { + return Result.buildFailure(VC_ITEM_JMX_NOT_EXIST); + } if (jmxInfo.getType() != null) { if (connectorType == null) { @@ -257,9 +278,6 @@ private Result getConnectorMetric(Long connectClusterId, Strin } } - if (null == jmxInfo) { - return Result.buildFailure(VC_ITEM_JMX_NOT_EXIST); - } String jmxObjectName = String.format(jmxInfo.getJmxObjectName(), connectorName); JmxConnectorWrap jmxConnectorWrap = connectJMXClient.getClientWithCheck(connectClusterId, workerId); @@ -270,8 +288,7 @@ private Result getConnectorMetric(Long connectClusterId, Strin try { //2、获取jmx指标 String value = jmxConnectorWrap.getAttribute(new ObjectName(jmxObjectName), jmxInfo.getJmxAttribute()).toString(); - ConnectorMetrics connectorMetrics = ConnectorMetrics.initWithMetric(connectClusterId, connectorName, metric, Float.valueOf(value)); - return Result.buildSuc(connectorMetrics); + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metric, Float.valueOf(value))); } catch (InstanceNotFoundException e) { // 忽略该错误,该错误出现的原因是该指标在JMX中不存在 return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName)); @@ -296,8 +313,7 @@ private Result getConnectorTaskMetricsAvg(VersionItemParam met } Float sum = ret.getData().stream().map(elem -> elem.getMetric(metric)).reduce(Float::sum).get(); - ConnectorMetrics connectorMetrics = ConnectorMetrics.initWithMetric(connectClusterId, connectorName, metric, sum / ret.getData().size()); - return Result.buildSuc(connectorMetrics); + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metric, sum / ret.getData().size())); } private Result getConnectorTaskMetricsMax(VersionItemParam metricParam){ @@ -313,8 +329,7 @@ private Result getConnectorTaskMetricsMax(VersionItemParam met } Float max = ret.getData().stream().max((a, b) -> a.getMetric(metric).compareTo(b.getMetric(metric))).get().getMetric(metric); - ConnectorMetrics connectorMetrics = ConnectorMetrics.initWithMetric(connectClusterId, connectorName, metric, max); - return Result.buildSuc(connectorMetrics); + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metric, max)); } private Result getConnectorTaskMetricsSum(VersionItemParam metricParam){ @@ -330,8 +345,7 @@ private Result getConnectorTaskMetricsSum(VersionItemParam met } Float sum = ret.getData().stream().map(elem -> elem.getMetric(metric)).reduce(Float::sum).get(); - ConnectorMetrics connectorMetrics = ConnectorMetrics.initWithMetric(connectClusterId, connectorName, metric, sum); - return Result.buildSuc(connectorMetrics); + return Result.buildSuc(new ConnectorMetrics(connectClusterId, connectorName, metric, sum)); } @@ -358,6 +372,9 @@ private Result> getConnectorTaskMetricList(Long conne private Result getConnectorTaskMetric(Long connectClusterId, String workerId, String connectorName, Integer taskId, String metric, ConnectorTypeEnum connectorType) { VersionConnectJmxInfo jmxInfo = getJMXInfo(connectClusterId, metric); + if (null == jmxInfo) { + return Result.buildFailure(VC_ITEM_JMX_NOT_EXIST); + } if (jmxInfo.getType() != null) { if (connectorType == null) { @@ -369,9 +386,6 @@ private Result getConnectorTaskMetric(Long connectClusterI } } - if (null == jmxInfo) { - return Result.buildFailure(VC_ITEM_JMX_NOT_EXIST); - } String jmxObjectName=String.format(jmxInfo.getJmxObjectName(), connectorName, taskId); JmxConnectorWrap jmxConnectorWrap = connectJMXClient.getClientWithCheck(connectClusterId, workerId); @@ -382,8 +396,7 @@ private Result getConnectorTaskMetric(Long connectClusterI try { //2、获取jmx指标 String value = jmxConnectorWrap.getAttribute(new ObjectName(jmxObjectName), jmxInfo.getJmxAttribute()).toString(); - ConnectorTaskMetrics connectorTaskMetrics = ConnectorTaskMetrics.initWithMetric(connectClusterId, connectorName, taskId, metric, Float.valueOf(value)); - return Result.buildSuc(connectorTaskMetrics); + return Result.buildSuc(new ConnectorTaskMetrics(connectClusterId, connectorName, taskId, metric, Float.valueOf(value))); } catch (Exception e) { LOGGER.error("method=getConnectorTaskMetric||connectClusterId={}||workerId={}||connectorName={}||taskId={}||metrics={}||jmx={}||msg={}", connectClusterId, workerId, connectorName, taskId, metric, jmxObjectName, e.getClass().getName()); diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/mm2/impl/MirrorMakerMetricServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/mm2/impl/MirrorMakerMetricServiceImpl.java index 83242841d..2361be963 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/mm2/impl/MirrorMakerMetricServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/mm2/impl/MirrorMakerMetricServiceImpl.java @@ -27,7 +27,7 @@ import com.xiaojukeji.know.streaming.km.core.service.connect.connector.ConnectorService; import com.xiaojukeji.know.streaming.km.core.service.connect.mm2.MirrorMakerMetricService; import com.xiaojukeji.know.streaming.km.core.service.health.state.HealthStateService; -import com.xiaojukeji.know.streaming.km.core.service.version.BaseConnectorMetricService; +import com.xiaojukeji.know.streaming.km.core.service.version.BaseConnectMetricService; import com.xiaojukeji.know.streaming.km.persistence.connect.ConnectJMXClient; import org.springframework.beans.factory.annotation.Autowired; import com.xiaojukeji.know.streaming.km.persistence.es.dao.connect.mm2.MirrorMakerMetricESDAO; @@ -49,7 +49,7 @@ * @date 2022/12/15 */ @Service -public class MirrorMakerMetricServiceImpl extends BaseConnectorMetricService implements MirrorMakerMetricService { +public class MirrorMakerMetricServiceImpl extends BaseConnectMetricService implements MirrorMakerMetricService { protected static final ILog LOGGER = LogFactory.getLog(MirrorMakerMetricServiceImpl.class); public static final String MIRROR_MAKER_METHOD_DO_NOTHING = "doNothing"; @@ -190,7 +190,7 @@ protected List metricMap2VO(Long connectClusterId, multiLinesVO.setMetricLines(metricLines); multiLinesVOS.add(multiLinesVO); - }catch (Exception e){ + } catch (Exception e){ LOGGER.error("method=metricMap2VO||connectClusterId={}||msg=exception!", connectClusterId, e); } } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectorMetricService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectMetricService.java similarity index 90% rename from km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectorMetricService.java rename to km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectMetricService.java index febfdcf44..da424ebc3 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectorMetricService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectMetricService.java @@ -9,7 +9,7 @@ * @author wyb * @date 2022/11/9 */ -public abstract class BaseConnectorMetricService extends BaseConnectorVersionControlService{ +public abstract class BaseConnectMetricService extends BaseConnectVersionControlService { private List metricNames = new ArrayList<>(); @PostConstruct diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectorVersionControlService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectVersionControlService.java similarity index 95% rename from km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectorVersionControlService.java rename to km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectVersionControlService.java index ced858ff6..8f4260614 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectorVersionControlService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/BaseConnectVersionControlService.java @@ -14,7 +14,7 @@ * @author wyb * @date 2022/11/8 */ -public abstract class BaseConnectorVersionControlService extends BaseVersionControlService { +public abstract class BaseConnectVersionControlService extends BaseVersionControlService { @Autowired ConnectClusterService connectClusterService; diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/connect/ConnectorMetricVersionItems.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/connect/ConnectorMetricVersionItems.java index 2d4aeac21..bcad6e3d4 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/connect/ConnectorMetricVersionItems.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/connect/ConnectorMetricVersionItems.java @@ -24,6 +24,8 @@ public class ConnectorMetricVersionItems extends BaseMetricVersionMetric { public static final String CONNECTOR_METRIC_HEALTH_STATE = "HealthState"; + public static final String CONNECTOR_METRIC_RUNNING_STATUS = "RunningStatus"; + public static final String CONNECTOR_METRIC_CONNECTOR_TOTAL_TASK_COUNT = "ConnectorTotalTaskCount"; public static final String CONNECTOR_METRIC_HEALTH_CHECK_PASSED = "HealthCheckPassed"; @@ -128,6 +130,9 @@ public List init() { items.add(buildAllVersionsItem() .name(CONNECTOR_METRIC_HEALTH_STATE).unit("0:好 1:中 2:差 3:宕机").desc("健康状态(0:好 1:中 2:差 3:宕机)").category(CATEGORY_HEALTH) .extendMethod(CONNECTOR_METHOD_GET_METRIC_HEALTH_SCORE)); + items.add(buildAllVersionsItem() + .name(CONNECTOR_METRIC_RUNNING_STATUS).unit("0:UNASSIGNED 1:RUNNING 2:PAUSED 3:FAILED 4:DESTROYED -1:UNKNOWN").desc("运行状态(0:UNASSIGNED 1:RUNNING 2:PAUSED 3:FAILED 4:DESTROYED -1:UNKNOWN)").category(CATEGORY_PERFORMANCE) + .extendMethod(CONNECTOR_METHOD_GET_METRIC_RUNNING_STATUS)); items.add(buildAllVersionsItem() .name(CONNECTOR_METRIC_HEALTH_CHECK_PASSED).unit("个").desc("健康项检查通过数").category(CATEGORY_HEALTH) .extendMethod(CONNECTOR_METHOD_GET_METRIC_HEALTH_SCORE)); diff --git a/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/common/MonitorSinkTagEnum.java b/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/common/MonitorSinkTagEnum.java index f78c547ad..3d8b5c25c 100644 --- a/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/common/MonitorSinkTagEnum.java +++ b/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/common/MonitorSinkTagEnum.java @@ -16,6 +16,11 @@ public enum MonitorSinkTagEnum { CONSUMER_GROUP("consumerGroup"), REPLICATION("replication"), + + CONNECT_CLUSTER_ID("connectClusterId"), + + CONNECT_CONNECTOR("connectConnector"), + ; private final String name; diff --git a/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/component/AbstractMonitorSinkService.java b/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/component/AbstractMonitorSinkService.java index bbb316475..6d6b97747 100644 --- a/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/component/AbstractMonitorSinkService.java +++ b/km-extends/km-monitor/src/main/java/com/xiaojukeji/know/streaming/km/monitor/component/AbstractMonitorSinkService.java @@ -3,7 +3,9 @@ import com.didiglobal.logi.log.ILog; import com.didiglobal.logi.log.LogFactory; import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.*; +import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.connect.ConnectorMetrics; import com.xiaojukeji.know.streaming.km.common.bean.event.metric.*; +import com.xiaojukeji.know.streaming.km.common.bean.event.metric.connect.ConnectorMetricEvent; import com.xiaojukeji.know.streaming.km.common.utils.FutureUtil; import com.xiaojukeji.know.streaming.km.monitor.common.MetricSinkPoint; import org.springframework.context.ApplicationListener; @@ -59,6 +61,10 @@ public void onApplicationEvent(BaseMetricEvent event) { } else if(event instanceof ZookeeperMetricEvent) { ZookeeperMetricEvent zookeeperMetricEvent = (ZookeeperMetricEvent)event; sinkMetrics(zookeeperMetric2SinkPoint(zookeeperMetricEvent.getZookeeperMetrics())); + + } else if (event instanceof ConnectorMetricEvent) { + ConnectorMetricEvent connectorMetricEvent = (ConnectorMetricEvent)event; + sinkMetrics(connectConnectorMetric2SinkPoint(connectorMetricEvent.getConnectorMetricsList())); } } ); } @@ -170,6 +176,21 @@ private List zookeeperMetric2SinkPoint(List z return pointList; } + private List connectConnectorMetric2SinkPoint(List connectorMetricsList){ + List pointList = new ArrayList<>(); + + for(ConnectorMetrics metrics : connectorMetricsList){ + Map tagsMap = new HashMap<>(); + tagsMap.put(CLUSTER_ID.getName(), metrics.getClusterPhyId()); + tagsMap.put(CONNECT_CLUSTER_ID.getName(), metrics.getConnectClusterId()); + tagsMap.put(CONNECT_CONNECTOR.getName(), metrics.getConnectorName()); + + pointList.addAll(genSinkPoint("ConnectConnector", metrics.getMetrics(), metrics.getTimestamp(), tagsMap)); + } + + return pointList; + } + private List genSinkPoint(String metricPre, Map metrics, long timeStamp, diff --git a/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/ConnectClusterMetricESDAO.java b/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/cluster/ConnectClusterMetricESDAO.java similarity index 99% rename from km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/ConnectClusterMetricESDAO.java rename to km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/cluster/ConnectClusterMetricESDAO.java index 31256efea..8d9626a53 100644 --- a/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/ConnectClusterMetricESDAO.java +++ b/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/es/dao/connect/cluster/ConnectClusterMetricESDAO.java @@ -1,4 +1,4 @@ -package com.xiaojukeji.know.streaming.km.persistence.es.dao.connect; +package com.xiaojukeji.know.streaming.km.persistence.es.dao.connect.cluster; import com.didiglobal.logi.elasticsearch.client.response.query.query.ESQueryResponse; import com.didiglobal.logi.elasticsearch.client.response.query.query.aggs.ESAggr; From db40a5cd0a6920e2972368554a49fda4b8298abb Mon Sep 17 00:00:00 2001 From: EricZeng Date: Wed, 2 Aug 2023 21:19:03 +0800 Subject: [PATCH 05/48] =?UTF-8?q?[Optimize]=E5=A2=9E=E5=8A=A0AdminClient?= =?UTF-8?q?=E8=A7=82=E6=B5=8B=E4=BF=A1=E6=81=AF=20(#1111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、增加AdminClient的ClientID; 2、关闭时,增加超时时间; 3、增加关闭错误的日志; --- .../core/service/group/impl/GroupServiceImpl.java | 2 ++ .../km/persistence/kafka/KafkaAdminClient.java | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java index 21511a96b..b0a7d7b56 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java @@ -78,6 +78,7 @@ public List listGroupsFromKafka(ClusterPhy clusterPhy) throws AdminOpera } props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, clusterPhy.getBootstrapServers()); + props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("KSPartialAdminClient||clusterPhyId=%d", clusterPhy.getId())); adminClient = KSPartialKafkaAdminClient.create(props); KSListGroupsResult listConsumerGroupsResult = adminClient.listConsumerGroups( @@ -178,6 +179,7 @@ public KSGroupDescription getGroupDescriptionFromKafka(ClusterPhy clusterPhy, St } props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, clusterPhy.getBootstrapServers()); + props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("KSPartialAdminClient||clusterPhyId=%d", clusterPhy.getId())); adminClient = KSPartialKafkaAdminClient.create(props); diff --git a/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/kafka/KafkaAdminClient.java b/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/kafka/KafkaAdminClient.java index 20447798c..fccf35dd4 100644 --- a/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/kafka/KafkaAdminClient.java +++ b/km-persistence/src/main/java/com/xiaojukeji/know/streaming/km/persistence/kafka/KafkaAdminClient.java @@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -76,10 +77,12 @@ private void closeKafkaAdminClient(Long clusterPhyId) { LOGGER.info("close kafka AdminClient starting, clusterPhyId:{}", clusterPhyId); - boolean allSuccess = this.closeAdminClientList(adminClientList); + boolean allSuccess = this.closeAdminClientList(clusterPhyId, adminClientList); if (allSuccess) { LOGGER.info("close kafka AdminClient success, clusterPhyId:{}", clusterPhyId); + } else { + LOGGER.error("close kafka AdminClient exist failed and can ignore this error, clusterPhyId:{}", clusterPhyId); } } catch (Exception e) { LOGGER.error("close kafka AdminClient failed, clusterPhyId:{}", clusterPhyId, e); @@ -116,6 +119,7 @@ private AdminClient createKafkaAdminClient(Long clusterPhyId, String bootstrapSe adminClientList = new ArrayList<>(); for (int i = 0; i < clientCnt; ++i) { + props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("ApacheAdminClient||clusterPhyId=%d||Cnt=%d", clusterPhyId, i)); adminClientList.add(AdminClient.create(props)); } @@ -125,7 +129,7 @@ private AdminClient createKafkaAdminClient(Long clusterPhyId, String bootstrapSe } catch (Exception e) { LOGGER.error("create kafka AdminClient failed, clusterPhyId:{} props:{}", clusterPhyId, props, e); - this.closeAdminClientList(adminClientList); + this.closeAdminClientList(clusterPhyId, adminClientList); } finally { modifyClientMapLock.unlock(); } @@ -133,7 +137,7 @@ private AdminClient createKafkaAdminClient(Long clusterPhyId, String bootstrapSe return KAFKA_ADMIN_CLIENT_MAP.get(clusterPhyId).get((int)(System.currentTimeMillis() % clientCnt)); } - private boolean closeAdminClientList(List adminClientList) { + private boolean closeAdminClientList(Long clusterPhyId, List adminClientList) { if (adminClientList == null) { return true; } @@ -141,9 +145,11 @@ private boolean closeAdminClientList(List adminClientList) { boolean allSuccess = true; for (AdminClient adminClient: adminClientList) { try { - adminClient.close(); + // 关闭客户端,超时时间为30秒 + adminClient.close(Duration.ofSeconds(30)); } catch (Exception e) { // ignore + LOGGER.error("close kafka AdminClient exist failed, clusterPhyId:{}", clusterPhyId, e); allSuccess = false; } } From ca696dd6e1953b7ad9cdbdfd336ff1655a94870f Mon Sep 17 00:00:00 2001 From: chang-wd <51365967+chang-wd@users.noreply.github.com> Date: Tue, 8 Aug 2023 14:49:25 +0800 Subject: [PATCH 06/48] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=9C=A8Lda?= =?UTF-8?q?p=E7=99=BB=E5=BD=95=E6=97=B6=EF=BC=8C=E8=AE=BE=E7=BD=AEauth-use?= =?UTF-8?q?r-registration:=20false=E4=BC=9A=E5=AF=BC=E8=87=B4=E7=A9=BA?= =?UTF-8?q?=E6=8C=87=E9=92=88=E7=9A=84=E9=97=AE=E9=A2=98=20(#1117)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure LDAP And Set auth-user-registration: false will result in NPE(Null Pointer Exception) #1116 --------- Co-authored-by: weidong_chang --- .../km/account/login/ldap/LdapLoginServiceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java b/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java index 64dc78ad9..aa56d842c 100644 --- a/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java +++ b/km-extends/km-account/src/main/java/com/xiaojukeji/know/streaming/km/account/login/ldap/LdapLoginServiceImpl.java @@ -16,8 +16,8 @@ import com.xiaojukeji.know.streaming.km.account.common.bizenum.LoginServiceNameEnum; import com.xiaojukeji.know.streaming.km.account.common.ldap.LdapPrincipal; import com.xiaojukeji.know.streaming.km.account.login.ldap.remote.LdapAuthentication; +import com.xiaojukeji.know.streaming.km.common.constant.Constant; import com.xiaojukeji.know.streaming.km.common.utils.CommonUtils; -import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,6 +80,10 @@ public UserBriefVO verifyLogin(AccountLoginDTO loginDTO, // user赋值 user = userService.getUserByUserName(ldapAttrsInfo.getSAMAccountName()); + } else if (ValidateUtils.isNull(user)) { + // user为空,且不自动注册用户时,赋值默认id给临时用户 + user = new User(); + user.setId(Constant.INVALID_CODE); } // 记录登录状态 From a6abfb3ea832a3a61aad172202ec95cdb9f94b46 Mon Sep 17 00:00:00 2001 From: EricZeng Date: Tue, 15 Aug 2023 14:21:05 +0800 Subject: [PATCH 07/48] =?UTF-8?q?[Doc]=E8=A1=A5=E5=85=85=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E8=AF=B4=E6=98=8E=20(#1126)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/user_guide/faq.md | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/user_guide/faq.md b/docs/user_guide/faq.md index b66523ff4..2897bf695 100644 --- a/docs/user_guide/faq.md +++ b/docs/user_guide/faq.md @@ -7,7 +7,7 @@ - [1、支持哪些 Kafka 版本?](#1支持哪些-kafka-版本) - [1、2.x 版本和 3.0 版本有什么差异?](#12x-版本和-30-版本有什么差异) - [3、页面流量信息等无数据?](#3页面流量信息等无数据) - - [8.4、`Jmx`连接失败如何解决?](#84jmx连接失败如何解决) + - [4、`Jmx`连接失败如何解决?](#4jmx连接失败如何解决) - [5、有没有 API 文档?](#5有没有-api-文档) - [6、删除 Topic 成功后,为何过段时间又出现了?](#6删除-topic-成功后为何过段时间又出现了) - [7、如何在不登录的情况下,调用接口?](#7如何在不登录的情况下调用接口) @@ -21,6 +21,7 @@ - [15、测试时使用Testcontainers的说明](#15测试时使用testcontainers的说明) - [16、JMX连接失败怎么办](#16jmx连接失败怎么办) - [17、zk监控无数据问题](#17zk监控无数据问题) + - [18、启动失败,报NoClassDefFoundError如何解决](#18启动失败报noclassdeffounderror如何解决) ## 1、支持哪些 Kafka 版本? @@ -57,7 +58,7 @@   -## 8.4、`Jmx`连接失败如何解决? +## 4、`Jmx`连接失败如何解决? - 参看 [Jmx 连接配置&问题解决](https://doc.knowstreaming.com/product/9-attachment#91jmx-%E8%BF%9E%E6%8E%A5%E5%A4%B1%E8%B4%A5%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3) 说明。 @@ -278,3 +279,31 @@ zookeeper集群正常,但Ks上zk页面所有监控指标无数据,`KnowStrea ``` 4lw.commands.whitelist=* ``` + +## 18、启动失败,报NoClassDefFoundError如何解决 + +**错误现象:** +```log +# 启动失败,报nested exception is java.lang.NoClassDefFoundError: Could not initialize class com.didiglobal.logi.job.core.WorkerSingleton$Singleton + + +2023-08-11 22:54:29.842 [main] ERROR class=org.springframework.boot.SpringApplication||Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzScheduler' defined in class path resource [com/didiglobal/logi/job/LogIJobAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.didiglobal.logi.job.core.Scheduler]: Factory method 'quartzScheduler' threw exception; nested exception is java.lang.NoClassDefFoundError: Could not initialize class com.didiglobal.logi.job.core.WorkerSingleton$Singleton +at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:657) +``` + + +**问题原因:** +1. `KnowStreaming` 依赖的 `Logi-Job` 初始化 `WorkerSingleton$Singleton` 失败。 +2. `WorkerSingleton$Singleton` 初始化的过程中,会去获取一些操作系统的信息,如果获取时出现了异常,则会导致 `WorkerSingleton$Singleton` 初始化失败。 + + +**临时建议:** + +`Logi-Job` 问题的修复时间不好控制,之前我们测试验证了一下,在 `Windows`、`Mac`、`CentOS` 这几个操作系统下基本上都是可以正常运行的。 + +所以,如果有条件的话,可以暂时先使用这几个系统部署 `KnowStreaming`。 + +如果在在 `Windows`、`Mac`、`CentOS` 这几个操作系统下也出现了启动失败的问题,可以重试2-3次看是否还是启动失败,或者换一台机器试试。 + + From 6e56688a3181c6517de68479562fb82373611290 Mon Sep 17 00:00:00 2001 From: EricZeng Date: Tue, 15 Aug 2023 14:24:23 +0800 Subject: [PATCH 08/48] =?UTF-8?q?[Optimize]=E7=BB=9F=E4=B8=80DB=E5=85=83?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=9B=B4=E6=96=B0=E6=A0=BC=E5=BC=8F-Part1=20?= =?UTF-8?q?(#1125)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、引入KafkaMetaService; 2、将Connector的更新按照KafkaMetaService进行更新; 3、简化Connect-MirrorMaker的关联逻辑; 4、GroupService创建的AdminClient中的ClientID增加时间戳,减少Mbean冲突; --- .../connector/impl/ConnectorManagerImpl.java | 18 +- .../mm2/impl/MirrorMakerManagerImpl.java | 34 +- .../ConnectConnectorMetricCollector.java | 2 +- .../bean/entity/meta/KafkaMetaService.java | 44 ++ .../km/common/converter/ConnectConverter.java | 65 ++ .../connect/connector/ConnectorService.java | 29 +- .../connect/connector/OpConnectorService.java | 26 + .../connector/impl/ConnectorServiceImpl.java | 560 ++++-------------- .../impl/OpConnectorServiceImpl.java | 352 +++++++++++ .../service/group/impl/GroupServiceImpl.java | 4 +- .../v3/connect/KafkaConnectorController.java | 13 +- .../connect/metadata/SyncConnectorTask.java | 43 +- 12 files changed, 652 insertions(+), 538 deletions(-) create mode 100644 km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java create mode 100644 km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/OpConnectorService.java create mode 100644 km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/OpConnectorServiceImpl.java diff --git a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/connector/impl/ConnectorManagerImpl.java b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/connector/impl/ConnectorManagerImpl.java index 191afc6bb..6e1440ef5 100644 --- a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/connector/impl/ConnectorManagerImpl.java +++ b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/connector/impl/ConnectorManagerImpl.java @@ -12,6 +12,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.vo.connect.connector.ConnectorStateVO; import com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant; import com.xiaojukeji.know.streaming.km.core.service.connect.connector.ConnectorService; +import com.xiaojukeji.know.streaming.km.core.service.connect.connector.OpConnectorService; import com.xiaojukeji.know.streaming.km.core.service.connect.plugin.PluginService; import com.xiaojukeji.know.streaming.km.core.service.connect.worker.WorkerConnectorService; import org.apache.kafka.connect.runtime.AbstractStatus; @@ -30,6 +31,9 @@ public class ConnectorManagerImpl implements ConnectorManager { @Autowired private ConnectorService connectorService; + @Autowired + private OpConnectorService opConnectorService; + @Autowired private WorkerConnectorService workerConnectorService; @@ -44,24 +48,24 @@ public Result updateConnectorConfig(Long connectClusterId, String connecto return Result.buildFromRSAndMsg(ResultStatus.PARAM_ILLEGAL, "Connector参数错误"); } - return connectorService.updateConnectorConfig(connectClusterId, connectorName, configs, operator); + return opConnectorService.updateConnectorConfig(connectClusterId, connectorName, configs, operator); } @Override public Result createConnector(ConnectorCreateDTO dto, String operator) { dto.getSuitableConfig().put(KafkaConnectConstant.MIRROR_MAKER_NAME_FIELD_NAME, dto.getConnectorName()); - Result createResult = connectorService.createConnector(dto.getConnectClusterId(), dto.getConnectorName(), dto.getSuitableConfig(), operator); + Result createResult = opConnectorService.createConnector(dto.getConnectClusterId(), dto.getConnectorName(), dto.getSuitableConfig(), operator); if (createResult.failed()) { return Result.buildFromIgnoreData(createResult); } - Result ksConnectorResult = connectorService.getAllConnectorInfoFromCluster(dto.getConnectClusterId(), dto.getConnectorName()); + Result ksConnectorResult = connectorService.getConnectorFromKafka(dto.getConnectClusterId(), dto.getConnectorName()); if (ksConnectorResult.failed()) { return Result.buildFromRSAndMsg(ResultStatus.SUCCESS, "创建成功,但是获取元信息失败,页面元信息会存在1分钟延迟"); } - connectorService.addNewToDB(ksConnectorResult.getData()); + opConnectorService.addNewToDB(ksConnectorResult.getData()); return Result.buildSuc(); } @@ -69,12 +73,12 @@ public Result createConnector(ConnectorCreateDTO dto, String operator) { public Result createConnector(ConnectorCreateDTO dto, String heartbeatName, String checkpointName, String operator) { dto.getSuitableConfig().put(KafkaConnectConstant.MIRROR_MAKER_NAME_FIELD_NAME, dto.getConnectorName()); - Result createResult = connectorService.createConnector(dto.getConnectClusterId(), dto.getConnectorName(), dto.getSuitableConfig(), operator); + Result createResult = opConnectorService.createConnector(dto.getConnectClusterId(), dto.getConnectorName(), dto.getSuitableConfig(), operator); if (createResult.failed()) { return Result.buildFromIgnoreData(createResult); } - Result ksConnectorResult = connectorService.getAllConnectorInfoFromCluster(dto.getConnectClusterId(), dto.getConnectorName()); + Result ksConnectorResult = connectorService.getConnectorFromKafka(dto.getConnectClusterId(), dto.getConnectorName()); if (ksConnectorResult.failed()) { return Result.buildFromRSAndMsg(ResultStatus.SUCCESS, "创建成功,但是获取元信息失败,页面元信息会存在1分钟延迟"); } @@ -83,7 +87,7 @@ public Result createConnector(ConnectorCreateDTO dto, String heartbeatName connector.setCheckpointConnectorName(checkpointName); connector.setHeartbeatConnectorName(heartbeatName); - connectorService.addNewToDB(connector); + opConnectorService.addNewToDB(connector); return Result.buildSuc(); } diff --git a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/mm2/impl/MirrorMakerManagerImpl.java b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/mm2/impl/MirrorMakerManagerImpl.java index de10b0f00..750220a7f 100644 --- a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/mm2/impl/MirrorMakerManagerImpl.java +++ b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/connect/mm2/impl/MirrorMakerManagerImpl.java @@ -37,6 +37,7 @@ import com.xiaojukeji.know.streaming.km.core.service.cluster.ClusterPhyService; import com.xiaojukeji.know.streaming.km.core.service.connect.cluster.ConnectClusterService; import com.xiaojukeji.know.streaming.km.core.service.connect.connector.ConnectorService; +import com.xiaojukeji.know.streaming.km.core.service.connect.connector.OpConnectorService; import com.xiaojukeji.know.streaming.km.core.service.connect.mm2.MirrorMakerMetricService; import com.xiaojukeji.know.streaming.km.core.service.connect.plugin.PluginService; import com.xiaojukeji.know.streaming.km.core.service.connect.worker.WorkerConnectorService; @@ -67,6 +68,9 @@ public class MirrorMakerManagerImpl implements MirrorMakerManager { @Autowired private ConnectorService connectorService; + @Autowired + private OpConnectorService opConnectorService; + @Autowired private WorkerConnectorService workerConnectorService; @@ -156,20 +160,20 @@ public Result deleteMirrorMaker(Long connectClusterId, String sourceConnec Result rv = Result.buildSuc(); if (!ValidateUtils.isBlank(connectorPO.getCheckpointConnectorName())) { - rv = connectorService.deleteConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); + rv = opConnectorService.deleteConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); } if (rv.failed()) { return rv; } if (!ValidateUtils.isBlank(connectorPO.getHeartbeatConnectorName())) { - rv = connectorService.deleteConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); + rv = opConnectorService.deleteConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); } if (rv.failed()) { return rv; } - return connectorService.deleteConnector(connectClusterId, sourceConnectorName, operator); + return opConnectorService.deleteConnector(connectClusterId, sourceConnectorName, operator); } @Override @@ -181,20 +185,20 @@ public Result modifyMirrorMakerConfig(MirrorMakerCreateDTO dto, String ope Result rv = Result.buildSuc(); if (!ValidateUtils.isBlank(connectorPO.getCheckpointConnectorName()) && dto.getCheckpointConnectorConfigs() != null) { - rv = connectorService.updateConnectorConfig(dto.getConnectClusterId(), connectorPO.getCheckpointConnectorName(), dto.getCheckpointConnectorConfigs(), operator); + rv = opConnectorService.updateConnectorConfig(dto.getConnectClusterId(), connectorPO.getCheckpointConnectorName(), dto.getCheckpointConnectorConfigs(), operator); } if (rv.failed()) { return rv; } if (!ValidateUtils.isBlank(connectorPO.getHeartbeatConnectorName()) && dto.getHeartbeatConnectorConfigs() != null) { - rv = connectorService.updateConnectorConfig(dto.getConnectClusterId(), connectorPO.getHeartbeatConnectorName(), dto.getHeartbeatConnectorConfigs(), operator); + rv = opConnectorService.updateConnectorConfig(dto.getConnectClusterId(), connectorPO.getHeartbeatConnectorName(), dto.getHeartbeatConnectorConfigs(), operator); } if (rv.failed()) { return rv; } - return connectorService.updateConnectorConfig(dto.getConnectClusterId(), dto.getConnectorName(), dto.getSuitableConfig(), operator); + return opConnectorService.updateConnectorConfig(dto.getConnectClusterId(), dto.getConnectorName(), dto.getSuitableConfig(), operator); } @Override @@ -206,20 +210,20 @@ public Result restartMirrorMaker(Long connectClusterId, String sourceConne Result rv = Result.buildSuc(); if (!ValidateUtils.isBlank(connectorPO.getCheckpointConnectorName())) { - rv = connectorService.restartConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); + rv = opConnectorService.restartConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); } if (rv.failed()) { return rv; } if (!ValidateUtils.isBlank(connectorPO.getHeartbeatConnectorName())) { - rv = connectorService.restartConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); + rv = opConnectorService.restartConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); } if (rv.failed()) { return rv; } - return connectorService.restartConnector(connectClusterId, sourceConnectorName, operator); + return opConnectorService.restartConnector(connectClusterId, sourceConnectorName, operator); } @Override @@ -231,20 +235,20 @@ public Result stopMirrorMaker(Long connectClusterId, String sourceConnecto Result rv = Result.buildSuc(); if (!ValidateUtils.isBlank(connectorPO.getCheckpointConnectorName())) { - rv = connectorService.stopConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); + rv = opConnectorService.stopConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); } if (rv.failed()) { return rv; } if (!ValidateUtils.isBlank(connectorPO.getHeartbeatConnectorName())) { - rv = connectorService.stopConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); + rv = opConnectorService.stopConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); } if (rv.failed()) { return rv; } - return connectorService.stopConnector(connectClusterId, sourceConnectorName, operator); + return opConnectorService.stopConnector(connectClusterId, sourceConnectorName, operator); } @Override @@ -256,20 +260,20 @@ public Result resumeMirrorMaker(Long connectClusterId, String sourceConnec Result rv = Result.buildSuc(); if (!ValidateUtils.isBlank(connectorPO.getCheckpointConnectorName())) { - rv = connectorService.resumeConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); + rv = opConnectorService.resumeConnector(connectClusterId, connectorPO.getCheckpointConnectorName(), operator); } if (rv.failed()) { return rv; } if (!ValidateUtils.isBlank(connectorPO.getHeartbeatConnectorName())) { - rv = connectorService.resumeConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); + rv = opConnectorService.resumeConnector(connectClusterId, connectorPO.getHeartbeatConnectorName(), operator); } if (rv.failed()) { return rv; } - return connectorService.resumeConnector(connectClusterId, sourceConnectorName, operator); + return opConnectorService.resumeConnector(connectClusterId, sourceConnectorName, operator); } @Override diff --git a/km-collector/src/main/java/com/xiaojukeji/know/streaming/km/collector/metric/connect/ConnectConnectorMetricCollector.java b/km-collector/src/main/java/com/xiaojukeji/know/streaming/km/collector/metric/connect/ConnectConnectorMetricCollector.java index 4da6d8fde..c49e1688e 100644 --- a/km-collector/src/main/java/com/xiaojukeji/know/streaming/km/collector/metric/connect/ConnectConnectorMetricCollector.java +++ b/km-collector/src/main/java/com/xiaojukeji/know/streaming/km/collector/metric/connect/ConnectConnectorMetricCollector.java @@ -44,7 +44,7 @@ public List collectConnectMetrics(ConnectCluster connectCluste Long connectClusterId = connectCluster.getId(); List items = versionControlService.listVersionControlItem(this.getClusterVersion(connectCluster), collectorType().getCode()); - Result> connectorList = connectorService.listConnectorsFromCluster(connectClusterId); + Result> connectorList = connectorService.listConnectorsFromCluster(connectCluster); FutureWaitUtil future = this.getFutureUtilByClusterPhyId(connectClusterId); diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java new file mode 100644 index 000000000..d0307afc2 --- /dev/null +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java @@ -0,0 +1,44 @@ +package com.xiaojukeji.know.streaming.km.common.bean.entity.meta; + +import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy; +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectCluster; +import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; +import com.xiaojukeji.know.streaming.km.common.utils.Tuple; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Kafka元信息服务接口 + */ +public interface KafkaMetaService { + /** + * 从Kafka中获取数据 + * @param connectCluster connect集群 + * @return 全部资源列表, 成功的资源列表 + */ + default Result, List>> getDataFromKafka(ConnectCluster connectCluster) { return Result.buildSuc(new Tuple<>(new HashSet<>(), new ArrayList<>())); } + + /** + * 从Kafka中获取数据 + * @param clusterPhy kafka集群 + * @return 全部资源集合, 成功的资源列表 + */ + default Result, List>> getDataFromKafka(ClusterPhy clusterPhy) { return Result.buildSuc(new Tuple<>(new HashSet<>(), new ArrayList<>())); } + + /** + * 元信息同步至DB中 + * @param clusterId 集群ID + * @param fullNameSet 全部资源列表 + * @param dataList 成功的资源列表 + */ + default void writeToDB(Long clusterId, Set fullNameSet, List dataList) {} + + /** + * 依据kafka集群ID删除数据 + * @param clusterPhyId kafka集群ID + */ + default int deleteInDBByKafkaClusterId(Long clusterPhyId) { return 0; } +} diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/converter/ConnectConverter.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/converter/ConnectConverter.java index 6dcc30e49..c20add65c 100644 --- a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/converter/ConnectConverter.java +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/converter/ConnectConverter.java @@ -16,6 +16,8 @@ import com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant; import com.xiaojukeji.know.streaming.km.common.utils.CommonUtils; import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; +import com.xiaojukeji.know.streaming.km.common.utils.Triple; +import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; import java.util.ArrayList; import java.util.HashMap; @@ -24,6 +26,9 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant.MIRROR_MAKER_SOURCE_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME; +import static com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant.MIRROR_MAKER_TARGET_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME; + public class ConnectConverter { public static ConnectorBasicCombineExistVO convert2BasicVO(ConnectCluster connectCluster, ConnectorPO connectorPO) { ConnectorBasicCombineExistVO vo = new ConnectorBasicCombineExistVO(); @@ -153,6 +158,66 @@ public static KSConnector convert2KSConnector(Long kafkaClusterPhyId, Long conne return ksConnector; } + public static List convertAndSupplyMirrorMakerInfo(ConnectCluster connectCluster, List, KSConnectorStateInfo>> connectorFullInfoList) { + // + Map sourceMap = new HashMap<>(); + + // + Map heartbeatMap = new HashMap<>(); + Map checkpointMap = new HashMap<>(); + + // 获取每个类型的connector的map信息 + connectorFullInfoList.forEach(connector -> { + Map mm2Map = null; + if (KafkaConnectConstant.MIRROR_MAKER_SOURCE_CONNECTOR_TYPE.equals(connector.v1().getConfig().get(KafkaConnectConstant.CONNECTOR_CLASS_FILED_NAME))) { + mm2Map = sourceMap; + } else if (KafkaConnectConstant.MIRROR_MAKER_HEARTBEAT_CONNECTOR_TYPE.equals(connector.v1().getConfig().get(KafkaConnectConstant.CONNECTOR_CLASS_FILED_NAME))) { + mm2Map = heartbeatMap; + } else if (KafkaConnectConstant.MIRROR_MAKER_CHECKPOINT_CONNECTOR_TYPE.equals(connector.v1().getConfig().get(KafkaConnectConstant.CONNECTOR_CLASS_FILED_NAME))) { + mm2Map = checkpointMap; + } + + String targetBootstrapServers = connector.v1().getConfig().get(MIRROR_MAKER_TARGET_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME); + String sourceBootstrapServers = connector.v1().getConfig().get(MIRROR_MAKER_SOURCE_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME); + + if (ValidateUtils.anyBlank(targetBootstrapServers, sourceBootstrapServers) || mm2Map == null) { + return; + } + + if (KafkaConnectConstant.MIRROR_MAKER_SOURCE_CONNECTOR_TYPE.equals(connector.v1().getConfig().get(KafkaConnectConstant.CONNECTOR_CLASS_FILED_NAME))) { + // source 类型的格式和 heartbeat & checkpoint 的不一样 + mm2Map.put(connector.v1().getName(), targetBootstrapServers + "@" + sourceBootstrapServers); + } else { + mm2Map.put(targetBootstrapServers + "@" + sourceBootstrapServers, connector.v1().getName()); + } + }); + + + List connectorList = new ArrayList<>(); + connectorFullInfoList.forEach(connector -> { + // 转化并添加到list中 + KSConnector ksConnector = ConnectConverter.convert2KSConnector( + connectCluster.getKafkaClusterPhyId(), + connectCluster.getId(), + connector.v1(), + connector.v3(), + connector.v2() + ); + connectorList.add(ksConnector); + + // 补充mm2信息 + String targetAndSource = sourceMap.get(ksConnector.getConnectorName()); + if (ValidateUtils.isBlank(targetAndSource)) { + return; + } + + ksConnector.setHeartbeatConnectorName(heartbeatMap.getOrDefault(targetAndSource, "")); + ksConnector.setCheckpointConnectorName(checkpointMap.getOrDefault(targetAndSource, "")); + }); + + return connectorList; + } + private static String genConnectorKey(Long connectorId, String connectorName){ return connectorId + "#" + connectorName; } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java index 220e4e895..7a85ffd28 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java @@ -4,49 +4,30 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnector; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorInfo; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorStateInfo; +import com.xiaojukeji.know.streaming.km.common.bean.entity.meta.KafkaMetaService; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.po.connect.ConnectorPO; import com.xiaojukeji.know.streaming.km.common.enums.connect.ConnectorTypeEnum; import java.util.List; -import java.util.Properties; -import java.util.Set; /** * 查看Connector */ -public interface ConnectorService { - Result createConnector(Long connectClusterId, String connectorName, Properties configs, String operator); - +public interface ConnectorService extends KafkaMetaService { /** * 获取所有的连接器名称列表 */ - Result> listConnectorsFromCluster(Long connectClusterId); + Result> listConnectorsFromCluster(ConnectCluster connectCluster); /** * 获取单个连接器信息 */ Result getConnectorInfoFromCluster(Long connectClusterId, String connectorName); - Result> getConnectorTopicsFromCluster(Long connectClusterId, String connectorName); - Result getConnectorStateInfoFromCluster(Long connectClusterId, String connectorName); - Result getAllConnectorInfoFromCluster(Long connectClusterId, String connectorName); - - Result resumeConnector(Long connectClusterId, String connectorName, String operator); - - Result restartConnector(Long connectClusterId, String connectorName, String operator); - - Result stopConnector(Long connectClusterId, String connectorName, String operator); - - Result deleteConnector(Long connectClusterId, String connectorName, String operator); - - Result updateConnectorConfig(Long connectClusterId, String connectorName, Properties configs, String operator); - - void batchReplace(Long kafkaClusterPhyId, Long connectClusterId, List connectorList, Set allConnectorNameSet); - - void addNewToDB(KSConnector connector); + Result getConnectorFromKafka(Long connectClusterId, String connectorName); List listByKafkaClusterIdFromDB(Long kafkaClusterPhyId); @@ -57,6 +38,4 @@ public interface ConnectorService { ConnectorPO getConnectorFromDB(Long connectClusterId, String connectorName); ConnectorTypeEnum getConnectorType(Long connectClusterId, String connectorName); - - void completeMirrorMakerInfo(ConnectCluster connectCluster, List connectorList); } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/OpConnectorService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/OpConnectorService.java new file mode 100644 index 000000000..f94c7c080 --- /dev/null +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/OpConnectorService.java @@ -0,0 +1,26 @@ +package com.xiaojukeji.know.streaming.km.core.service.connect.connector; + +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnector; +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorInfo; +import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; + +import java.util.Properties; + +/** + * 查看Connector + */ +public interface OpConnectorService { + Result createConnector(Long connectClusterId, String connectorName, Properties configs, String operator); + + Result resumeConnector(Long connectClusterId, String connectorName, String operator); + + Result restartConnector(Long connectClusterId, String connectorName, String operator); + + Result stopConnector(Long connectClusterId, String connectorName, String operator); + + Result deleteConnector(Long connectClusterId, String connectorName, String operator); + + Result updateConnectorConfig(Long connectClusterId, String connectorName, Properties configs, String operator); + + void addNewToDB(KSConnector connector); +} diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorServiceImpl.java index 133355a84..74c298b50 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/ConnectorServiceImpl.java @@ -3,7 +3,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.didiglobal.logi.log.ILog; import com.didiglobal.logi.log.LogFactory; -import com.didiglobal.logi.security.common.dto.oplog.OplogDTO; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectCluster; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnector; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorInfo; @@ -13,19 +12,14 @@ import com.xiaojukeji.know.streaming.km.common.bean.po.connect.ConnectorPO; import com.xiaojukeji.know.streaming.km.common.component.RestTool; import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; -import com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant; import com.xiaojukeji.know.streaming.km.common.converter.ConnectConverter; import com.xiaojukeji.know.streaming.km.common.enums.connect.ConnectorTypeEnum; -import com.xiaojukeji.know.streaming.km.common.enums.operaterecord.ModuleEnum; -import com.xiaojukeji.know.streaming.km.common.enums.operaterecord.OperationEnum; -import com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum; -import com.xiaojukeji.know.streaming.km.common.utils.BackoffUtils; import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; +import com.xiaojukeji.know.streaming.km.common.utils.Triple; +import com.xiaojukeji.know.streaming.km.common.utils.Tuple; import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; import com.xiaojukeji.know.streaming.km.core.service.connect.cluster.ConnectClusterService; import com.xiaojukeji.know.streaming.km.core.service.connect.connector.ConnectorService; -import com.xiaojukeji.know.streaming.km.core.service.oprecord.OpLogWrapService; -import com.xiaojukeji.know.streaming.km.core.service.version.BaseVersionControlService; import com.xiaojukeji.know.streaming.km.persistence.mysql.connect.ConnectorDAO; import org.apache.kafka.connect.runtime.rest.entities.ActiveTopicsInfo; import org.apache.kafka.connect.runtime.rest.entities.ConnectorInfo; @@ -34,14 +28,9 @@ import org.springframework.stereotype.Service; import java.util.*; -import java.util.stream.Collectors; - -import static com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant.MIRROR_MAKER_SOURCE_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME; -import static com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant.MIRROR_MAKER_TARGET_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME; -import static com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum.SERVICE_OP_CONNECT_CONNECTOR; @Service -public class ConnectorServiceImpl extends BaseVersionControlService implements ConnectorService { +public class ConnectorServiceImpl implements ConnectorService { private static final ILog LOGGER = LogFactory.getLog(ConnectorServiceImpl.class); @Autowired @@ -53,79 +42,14 @@ public class ConnectorServiceImpl extends BaseVersionControlService implements C @Autowired private ConnectClusterService connectClusterService; - @Autowired - private OpLogWrapService opLogWrapService; - private static final String LIST_CONNECTORS_URI = "/connectors"; private static final String GET_CONNECTOR_INFO_PREFIX_URI = "/connectors"; private static final String GET_CONNECTOR_TOPICS_URI = "/connectors/%s/topics"; private static final String GET_CONNECTOR_STATUS_URI = "/connectors/%s/status"; - private static final String CREATE_CONNECTOR_URI = "/connectors"; - private static final String RESUME_CONNECTOR_URI = "/connectors/%s/resume"; - private static final String RESTART_CONNECTOR_URI = "/connectors/%s/restart"; - private static final String PAUSE_CONNECTOR_URI = "/connectors/%s/pause"; - private static final String DELETE_CONNECTOR_URI = "/connectors/%s"; - private static final String UPDATE_CONNECTOR_CONFIG_URI = "/connectors/%s/config"; - @Override - protected VersionItemTypeEnum getVersionItemType() { - return SERVICE_OP_CONNECT_CONNECTOR; - } - - @Override - public Result createConnector(Long connectClusterId, String connectorName, Properties configs, String operator) { + public Result> listConnectorsFromCluster(ConnectCluster connectCluster) { try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - // 构造参数 - Properties props = new Properties(); - props.put(KafkaConnectConstant.MIRROR_MAKER_NAME_FIELD_NAME, connectorName); - props.put("config", configs); - - ConnectorInfo connectorInfo = restTool.postObjectWithJsonContent( - connectCluster.getSuitableRequestUrl() + CREATE_CONNECTOR_URI, - props, - ConnectorInfo.class - ); - - opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( - operator, - OperationEnum.ADD.getDesc(), - ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), - MsgConstant.getConnectorBizStr(connectClusterId, connectorName), - ConvertUtil.obj2Json(configs) - )); - - KSConnectorInfo connector = new KSConnectorInfo(); - connector.setConnectClusterId(connectClusterId); - connector.setConfig(connectorInfo.config()); - connector.setName(connectorInfo.name()); - connector.setTasks(connectorInfo.tasks()); - connector.setType(connectorInfo.type()); - - return Result.buildSuc(connector); - } catch (Exception e) { - LOGGER.error( - "method=createConnector||connectClusterId={}||connectorName={}||configs={}||operator={}||errMsg=exception", - connectClusterId, connectorName, configs, operator, e - ); - - return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); - } - } - - @Override - public Result> listConnectorsFromCluster(Long connectClusterId) { - try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - List nameList = restTool.getArrayObjectWithJsonContent( connectCluster.getSuitableRequestUrl() + LIST_CONNECTORS_URI, new HashMap<>(), @@ -135,8 +59,8 @@ public Result> listConnectorsFromCluster(Long connectClusterId) { return Result.buildSuc(nameList); } catch (Exception e) { LOGGER.error( - "method=listConnectorsFromCluster||connectClusterId={}||errMsg=exception", - connectClusterId, e + "method=listConnectorsFromCluster||connectClusterId={}||connectClusterSuitableUrl={}||errMsg=exception", + connectCluster.getId(), connectCluster.getSuitableRequestUrl(), e ); return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); @@ -153,16 +77,6 @@ public Result getConnectorInfoFromCluster(Long connectClusterId return this.getConnectorInfoFromCluster(connectCluster, connectorName); } - @Override - public Result> getConnectorTopicsFromCluster(Long connectClusterId, String connectorName) { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - return this.getConnectorTopicsFromCluster(connectCluster, connectorName); - } - @Override public Result getConnectorStateInfoFromCluster(Long connectClusterId, String connectorName) { ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); @@ -174,270 +88,26 @@ public Result getConnectorStateInfoFromCluster(Long connec } @Override - public Result getAllConnectorInfoFromCluster(Long connectClusterId, String connectorName) { + public Result getConnectorFromKafka(Long connectClusterId, String connectorName) { ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); if (ValidateUtils.isNull(connectCluster)) { return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); } - Result connectorResult = this.getConnectorInfoFromCluster(connectCluster, connectorName); - if (connectorResult.failed()) { - LOGGER.error( - "method=getAllConnectorInfoFromCluster||connectClusterId={}||connectorName={}||result={}", - connectClusterId, connectorName, connectorResult - ); - - return Result.buildFromIgnoreData(connectorResult); - } - - Result> topicNameListResult = this.getConnectorTopicsFromCluster(connectCluster, connectorName); - if (topicNameListResult.failed()) { - LOGGER.error( - "method=getAllConnectorInfoFromCluster||connectClusterId={}||connectorName={}||result={}", - connectClusterId, connectorName, connectorResult - ); - } - - Result stateInfoResult = this.getConnectorStateInfoFromCluster(connectCluster, connectorName); - if (stateInfoResult.failed()) { - LOGGER.error( - "method=getAllConnectorInfoFromCluster||connectClusterId={}||connectorName={}||result={}", - connectClusterId, connectorName, connectorResult - ); + Result, KSConnectorStateInfo>> fullInfoResult = this.getConnectorFullInfoFromKafka(connectCluster, connectorName); + if (fullInfoResult.failed()) { + return Result.buildFromIgnoreData(fullInfoResult); } return Result.buildSuc(ConnectConverter.convert2KSConnector( connectCluster.getKafkaClusterPhyId(), connectCluster.getId(), - connectorResult.getData(), - stateInfoResult.getData(), - topicNameListResult.getData() + fullInfoResult.getData().v1(), + fullInfoResult.getData().v3(), + fullInfoResult.getData().v2() )); } - @Override - public Result resumeConnector(Long connectClusterId, String connectorName, String operator) { - try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - restTool.putJsonForObject( - connectCluster.getSuitableRequestUrl() + String.format(RESUME_CONNECTOR_URI, connectorName), - new HashMap<>(), - String.class - ); - - this.updateStatus(connectCluster, connectClusterId, connectorName); - - opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( - operator, - OperationEnum.ENABLE.getDesc(), - ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), - MsgConstant.getConnectorBizStr(connectClusterId, connectorName), - "" - )); - - return Result.buildSuc(); - } catch (Exception e) { - LOGGER.error( - "class=ConnectorServiceImpl||method=resumeConnector||connectClusterId={}||errMsg=exception", - connectClusterId, e - ); - - return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); - } - } - - @Override - public Result restartConnector(Long connectClusterId, String connectorName, String operator) { - try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - restTool.postObjectWithJsonContent( - connectCluster.getSuitableRequestUrl() + String.format(RESTART_CONNECTOR_URI, connectorName), - new HashMap<>(), - String.class - ); - - this.updateStatus(connectCluster, connectClusterId, connectorName); - - opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( - operator, - OperationEnum.RESTART.getDesc(), - ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), - MsgConstant.getConnectorBizStr(connectClusterId, connectorName), - "" - )); - - return Result.buildSuc(); - } catch (Exception e) { - LOGGER.error( - "method=restartConnector||connectClusterId={}||errMsg=exception", - connectClusterId, e - ); - - return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); - } - } - - @Override - public Result stopConnector(Long connectClusterId, String connectorName, String operator) { - try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - restTool.putJsonForObject( - connectCluster.getSuitableRequestUrl() + String.format(PAUSE_CONNECTOR_URI, connectorName), - new HashMap<>(), - String.class - ); - - this.updateStatus(connectCluster, connectClusterId, connectorName); - - opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( - operator, - OperationEnum.DISABLE.getDesc(), - ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), - MsgConstant.getConnectorBizStr(connectClusterId, connectorName), - "" - )); - - return Result.buildSuc(); - } catch (Exception e) { - LOGGER.error( - "method=stopConnector||connectClusterId={}||errMsg=exception", - connectClusterId, e - ); - - return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); - } - } - - @Override - public Result deleteConnector(Long connectClusterId, String connectorName, String operator) { - try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - restTool.deleteWithParamsAndHeader( - connectCluster.getSuitableRequestUrl() + String.format(DELETE_CONNECTOR_URI, connectorName), - new HashMap<>(), - new HashMap<>(), - String.class - ); - - opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( - operator, - OperationEnum.DELETE.getDesc(), - ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), - MsgConstant.getConnectorBizStr(connectClusterId, connectorName), - "" - )); - - this.deleteConnectorInDB(connectClusterId, connectorName); - - return Result.buildSuc(); - } catch (Exception e) { - LOGGER.error( - "method=deleteConnector||connectClusterId={}||errMsg=exception", - connectClusterId, e - ); - - return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); - } - } - - @Override - public Result updateConnectorConfig(Long connectClusterId, String connectorName, Properties configs, String operator) { - try { - ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); - if (ValidateUtils.isNull(connectCluster)) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); - } - - ConnectorInfo connectorInfo = restTool.putJsonForObject( - connectCluster.getSuitableRequestUrl() + String.format(UPDATE_CONNECTOR_CONFIG_URI, connectorName), - configs, - org.apache.kafka.connect.runtime.rest.entities.ConnectorInfo.class - ); - - this.updateStatus(connectCluster, connectClusterId, connectorName); - - opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( - operator, - OperationEnum.EDIT.getDesc(), - ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), - MsgConstant.getConnectorBizStr(connectClusterId, connectorName), - ConvertUtil.obj2Json(configs) - )); - - return Result.buildSuc(); - } catch (Exception e) { - LOGGER.error( - "method=updateConnectorConfig||connectClusterId={}||errMsg=exception", - connectClusterId, e - ); - - return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); - } - } - - @Override - public void batchReplace(Long kafkaClusterPhyId, Long connectClusterId, List connectorList, Set allConnectorNameSet) { - List poList = this.listByConnectClusterIdFromDB(connectClusterId); - - Map oldPOMap = new HashMap<>(); - poList.forEach(elem -> oldPOMap.put(elem.getConnectorName(), elem)); - - for (KSConnector connector: connectorList) { - try { - ConnectorPO oldPO = oldPOMap.remove(connector.getConnectorName()); - if (oldPO == null) { - oldPO = ConvertUtil.obj2Obj(connector, ConnectorPO.class); - connectorDAO.insert(oldPO); - } else { - ConnectorPO newPO = ConvertUtil.obj2Obj(connector, ConnectorPO.class); - newPO.setId(oldPO.getId()); - connectorDAO.updateById(newPO); - } - } catch (DuplicateKeyException dke) { - // ignore - } - } - - try { - oldPOMap.values().forEach(elem -> { - if (allConnectorNameSet.contains(elem.getConnectorName())) { - // 当前connector还存在 - return; - } - - // 当前connector不存在了,则进行删除 - connectorDAO.deleteById(elem.getId()); - }); - } catch (Exception e) { - // ignore - } - } - - @Override - public void addNewToDB(KSConnector connector) { - try { - connectorDAO.insert(ConvertUtil.obj2Obj(connector, ConnectorPO.class)); - } catch (DuplicateKeyException dke) { - // ignore - } - } - @Override public List listByKafkaClusterIdFromDB(Long kafkaClusterPhyId) { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); @@ -482,53 +152,98 @@ public ConnectorTypeEnum getConnectorType(Long connectClusterId, String connecto } @Override - public void completeMirrorMakerInfo(ConnectCluster connectCluster, List connectorList) { - List sourceConnectorList = connectorList.stream().filter(elem -> elem.getConnectorClassName().equals(KafkaConnectConstant.MIRROR_MAKER_SOURCE_CONNECTOR_TYPE)).collect(Collectors.toList()); - if (sourceConnectorList.isEmpty()) { - return; + public Result, List>> getDataFromKafka(ConnectCluster connectCluster) { + Result> nameListResult = this.listConnectorsFromCluster(connectCluster); + if (nameListResult.failed()) { + return Result.buildFromIgnoreData(nameListResult); + } + + // 逐个获取 + List, KSConnectorStateInfo>> connectorFullInfoList = new ArrayList<>(); + for (String connectorName: nameListResult.getData()) { + Result, KSConnectorStateInfo>> ksConnectorResult = this.getConnectorFullInfoFromKafka(connectCluster, connectorName); + if (ksConnectorResult.failed()) { + continue; + } + + connectorFullInfoList.add(ksConnectorResult.getData()); } - List heartBeatConnectorList = connectorList.stream().filter(elem -> elem.getConnectorClassName().equals(KafkaConnectConstant.MIRROR_MAKER_HEARTBEAT_CONNECTOR_TYPE)).collect(Collectors.toList()); - List checkpointConnectorList = connectorList.stream().filter(elem -> elem.getConnectorClassName().equals(KafkaConnectConstant.MIRROR_MAKER_CHECKPOINT_CONNECTOR_TYPE)).collect(Collectors.toList()); + // 返回结果 + return Result.buildSuc(new Tuple<>( + new HashSet<>(nameListResult.getData()), + ConnectConverter.convertAndSupplyMirrorMakerInfo(connectCluster, connectorFullInfoList)) // 转换并补充mm2相关信息 + ); + } + + @Override + public void writeToDB(Long connectClusterId, Set fullNameSet, List dataList) { + List poList = this.listByConnectClusterIdFromDB(connectClusterId); + + Map oldPOMap = new HashMap<>(); + poList.forEach(elem -> oldPOMap.put(elem.getConnectorName(), elem)); + + for (KSConnector connector: dataList) { + try { + ConnectorPO oldPO = oldPOMap.remove(connector.getConnectorName()); + if (oldPO == null) { + oldPO = ConvertUtil.obj2Obj(connector, ConnectorPO.class); + connectorDAO.insert(oldPO); + continue; + } - Map heartbeatMap = this.buildMirrorMakerMap(connectCluster, heartBeatConnectorList); - Map checkpointMap = this.buildMirrorMakerMap(connectCluster, checkpointConnectorList); + ConnectorPO newPO = ConvertUtil.obj2Obj(connector, ConnectorPO.class); + newPO.setId(oldPO.getId()); + if (!ValidateUtils.isBlank(oldPO.getCheckpointConnectorName()) + && ValidateUtils.isBlank(newPO.getCheckpointConnectorName()) + && fullNameSet.contains(oldPO.getCheckpointConnectorName())) { + // 新的po里面没有checkpoint的信息,但是db中的数据显示有,且集群中有该connector,则保留该checkpoint数据 + newPO.setCheckpointConnectorName(oldPO.getCheckpointConnectorName()); + } - for (KSConnector sourceConnector : sourceConnectorList) { - Result ret = this.getConnectorInfoFromCluster(connectCluster, sourceConnector.getConnectorName()); + if (!ValidateUtils.isBlank(oldPO.getHeartbeatConnectorName()) + && ValidateUtils.isBlank(newPO.getHeartbeatConnectorName()) + && fullNameSet.contains(oldPO.getHeartbeatConnectorName())) { + // 新的po里面没有checkpoint的信息,但是db中的数据显示有,且集群中有该connector,则保留该checkpoint数据 + newPO.setHeartbeatConnectorName(oldPO.getHeartbeatConnectorName()); + } - if (!ret.hasData()) { + connectorDAO.updateById(newPO); + } catch (DuplicateKeyException dke) { + // ignore + } catch (Exception e) { LOGGER.error( - "method=completeMirrorMakerInfo||connectClusterId={}||connectorName={}||get connectorInfo fail!", - connectCluster.getId(), sourceConnector.getConnectorName() + "method=writeToDB||connectClusterId={}||connectorName={}||errMsg=exception", + connector.getConnectClusterId(), connector.getConnectorName(), e ); - continue; } - KSConnectorInfo ksConnectorInfo = ret.getData(); - String targetServers = ksConnectorInfo.getConfig().get(MIRROR_MAKER_TARGET_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME); - String sourceServers = ksConnectorInfo.getConfig().get(MIRROR_MAKER_SOURCE_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME); + } - if (ValidateUtils.anyBlank(targetServers, sourceServers)) { - continue; - } + try { + oldPOMap.values().forEach(elem -> { + if (fullNameSet.contains(elem.getConnectorName())) { + // 当前connector还存在 + return; + } - String[] targetBrokerList = getBrokerList(targetServers); - String[] sourceBrokerList = getBrokerList(sourceServers); - sourceConnector.setHeartbeatConnectorName(this.findBindConnector(targetBrokerList, sourceBrokerList, heartbeatMap)); - sourceConnector.setCheckpointConnectorName(this.findBindConnector(targetBrokerList, sourceBrokerList, checkpointMap)); + // 当前connector不存在了,则进行删除 + connectorDAO.deleteById(elem.getId()); + }); + } catch (Exception e) { + // ignore } - } - /**************************************************** private method ****************************************************/ - private int deleteConnectorInDB(Long connectClusterId, String connectorName) { + @Override + public int deleteInDBByKafkaClusterId(Long clusterPhyId) { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(ConnectorPO::getConnectClusterId, connectClusterId); - lambdaQueryWrapper.eq(ConnectorPO::getConnectorName, connectorName); + lambdaQueryWrapper.eq(ConnectorPO::getKafkaClusterPhyId, clusterPhyId); return connectorDAO.delete(lambdaQueryWrapper); } + /**************************************************** private method ****************************************************/ + private Result getConnectorInfoFromCluster(ConnectCluster connectCluster, String connectorName) { try { ConnectorInfo connectorInfo = restTool.getForObject( @@ -594,90 +309,37 @@ private Result getConnectorStateInfoFromCluster(ConnectClu } } - private void updateStatus(ConnectCluster connectCluster, Long connectClusterId, String connectorName) { - try { - // 延迟3秒 - BackoffUtils.backoff(2000); - - Result stateInfoResult = this.getConnectorStateInfoFromCluster(connectCluster, connectorName); - if (stateInfoResult.failed()) { - return; - } - - ConnectorPO po = new ConnectorPO(); - po.setConnectClusterId(connectClusterId); - po.setConnectorName(connectorName); - po.setState(stateInfoResult.getData().getConnector().getState()); - - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(ConnectorPO::getConnectClusterId, connectClusterId); - lambdaQueryWrapper.eq(ConnectorPO::getConnectorName, connectorName); - - connectorDAO.update(po, lambdaQueryWrapper); - } catch (Exception e) { + private Result, KSConnectorStateInfo>> getConnectorFullInfoFromKafka(ConnectCluster connectCluster, String connectorName) { + Result connectorResult = this.getConnectorInfoFromCluster(connectCluster, connectorName); + if (connectorResult.failed()) { LOGGER.error( - "method=updateStatus||connectClusterId={}||connectorName={}||errMsg=exception", - connectClusterId, connectorName, e + "method=getConnectorAllInfoFromKafka||connectClusterId={}||connectClusterSuitableUrl={}||result={}||errMsg=get connectors info from cluster failed", + connectCluster.getId(), connectCluster.getSuitableRequestUrl(), connectorResult ); - } - } - - private Map buildMirrorMakerMap(ConnectCluster connectCluster, List ksConnectorList) { - Map bindMap = new HashMap<>(); - - for (KSConnector ksConnector : ksConnectorList) { - Result ret = this.getConnectorInfoFromCluster(connectCluster, ksConnector.getConnectorName()); - - if (!ret.hasData()) { - LOGGER.error( - "method=buildMirrorMakerMap||connectClusterId={}||connectorName={}||get connectorInfo fail!", - connectCluster.getId(), ksConnector.getConnectorName() - ); - continue; - } - - KSConnectorInfo ksConnectorInfo = ret.getData(); - String targetServers = ksConnectorInfo.getConfig().get(MIRROR_MAKER_TARGET_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME); - String sourceServers = ksConnectorInfo.getConfig().get(MIRROR_MAKER_SOURCE_CLUSTER_BOOTSTRAP_SERVERS_FIELD_NAME); - - if (ValidateUtils.anyBlank(targetServers, sourceServers)) { - continue; - } - - String[] targetBrokerList = getBrokerList(targetServers); - String[] sourceBrokerList = getBrokerList(sourceServers); - for (String targetBroker : targetBrokerList) { - for (String sourceBroker : sourceBrokerList) { - bindMap.put(targetBroker + "@" + sourceBroker, ksConnector.getConnectorName()); - } - } + return Result.buildFromIgnoreData(connectorResult); } - return bindMap; - } - private String findBindConnector(String[] targetBrokerList, String[] sourceBrokerList, Map connectorBindMap) { - for (String targetBroker : targetBrokerList) { - for (String sourceBroker : sourceBrokerList) { - String connectorName = connectorBindMap.get(targetBroker + "@" + sourceBroker); - if (connectorName != null) { - return connectorName; - } - } + Result> topicNameListResult = this.getConnectorTopicsFromCluster(connectCluster, connectorName); + if (topicNameListResult.failed()) { + LOGGER.error( + "method=getConnectorAllInfoFromKafka||connectClusterId={}||connectClusterSuitableUrl={}||result={}||errMsg=get connectors topics from cluster failed", + connectCluster.getId(), connectCluster.getSuitableRequestUrl(), topicNameListResult + ); } - return ""; - } - private String[] getBrokerList(String str) { - if (ValidateUtils.isBlank(str)) { - return new String[0]; - } - if (str.contains(";")) { - return str.split(";"); - } - if (str.contains(",")) { - return str.split(","); + Result stateInfoResult = this.getConnectorStateInfoFromCluster(connectCluster, connectorName); + if (stateInfoResult.failed()) { + LOGGER.error( + "method=getConnectorAllInfoFromKafka||connectClusterId={}||connectClusterSuitableUrl={}||result={}||errMsg=get connectors state from cluster failed", + connectCluster.getId(), connectCluster.getSuitableRequestUrl(), stateInfoResult + ); } - return new String[]{str}; + + return Result.buildSuc(new Triple<>( + connectorResult.getData(), + topicNameListResult.getData(), + stateInfoResult.getData() + )); } } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/OpConnectorServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/OpConnectorServiceImpl.java new file mode 100644 index 000000000..df0e96330 --- /dev/null +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/impl/OpConnectorServiceImpl.java @@ -0,0 +1,352 @@ +package com.xiaojukeji.know.streaming.km.core.service.connect.connector.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.didiglobal.logi.log.ILog; +import com.didiglobal.logi.log.LogFactory; +import com.didiglobal.logi.security.common.dto.oplog.OplogDTO; +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectCluster; +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnector; +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorInfo; +import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorStateInfo; +import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; +import com.xiaojukeji.know.streaming.km.common.bean.entity.result.ResultStatus; +import com.xiaojukeji.know.streaming.km.common.bean.po.connect.ConnectorPO; +import com.xiaojukeji.know.streaming.km.common.component.RestTool; +import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; +import com.xiaojukeji.know.streaming.km.common.constant.connect.KafkaConnectConstant; +import com.xiaojukeji.know.streaming.km.common.enums.operaterecord.ModuleEnum; +import com.xiaojukeji.know.streaming.km.common.enums.operaterecord.OperationEnum; +import com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum; +import com.xiaojukeji.know.streaming.km.common.utils.BackoffUtils; +import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; +import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; +import com.xiaojukeji.know.streaming.km.core.service.connect.cluster.ConnectClusterService; +import com.xiaojukeji.know.streaming.km.core.service.connect.connector.OpConnectorService; +import com.xiaojukeji.know.streaming.km.core.service.oprecord.OpLogWrapService; +import com.xiaojukeji.know.streaming.km.core.service.version.BaseVersionControlService; +import com.xiaojukeji.know.streaming.km.persistence.mysql.connect.ConnectorDAO; +import org.apache.kafka.connect.runtime.rest.entities.ConnectorInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Service; + +import java.util.*; + +import static com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum.SERVICE_OP_CONNECT_CONNECTOR; + +@Service +public class OpConnectorServiceImpl extends BaseVersionControlService implements OpConnectorService { + private static final ILog LOGGER = LogFactory.getLog(OpConnectorServiceImpl.class); + + @Autowired + private RestTool restTool; + + @Autowired + private ConnectorDAO connectorDAO; + + @Autowired + private ConnectClusterService connectClusterService; + + @Autowired + private OpLogWrapService opLogWrapService; + + private static final String GET_CONNECTOR_STATUS_URI = "/connectors/%s/status"; + + private static final String CREATE_CONNECTOR_URI = "/connectors"; + private static final String RESUME_CONNECTOR_URI = "/connectors/%s/resume"; + private static final String RESTART_CONNECTOR_URI = "/connectors/%s/restart"; + private static final String PAUSE_CONNECTOR_URI = "/connectors/%s/pause"; + private static final String DELETE_CONNECTOR_URI = "/connectors/%s"; + private static final String UPDATE_CONNECTOR_CONFIG_URI = "/connectors/%s/config"; + + @Override + protected VersionItemTypeEnum getVersionItemType() { + return SERVICE_OP_CONNECT_CONNECTOR; + } + + @Override + public Result createConnector(Long connectClusterId, String connectorName, Properties configs, String operator) { + try { + ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); + if (ValidateUtils.isNull(connectCluster)) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); + } + + // 构造参数 + Properties props = new Properties(); + props.put(KafkaConnectConstant.MIRROR_MAKER_NAME_FIELD_NAME, connectorName); + props.put("config", configs); + + ConnectorInfo connectorInfo = restTool.postObjectWithJsonContent( + connectCluster.getSuitableRequestUrl() + CREATE_CONNECTOR_URI, + props, + ConnectorInfo.class + ); + + opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( + operator, + OperationEnum.ADD.getDesc(), + ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), + MsgConstant.getConnectorBizStr(connectClusterId, connectorName), + ConvertUtil.obj2Json(configs) + )); + + KSConnectorInfo connector = new KSConnectorInfo(); + connector.setConnectClusterId(connectClusterId); + connector.setConfig(connectorInfo.config()); + connector.setName(connectorInfo.name()); + connector.setTasks(connectorInfo.tasks()); + connector.setType(connectorInfo.type()); + + return Result.buildSuc(connector); + } catch (Exception e) { + LOGGER.error( + "method=createConnector||connectClusterId={}||connectorName={}||configs={}||operator={}||errMsg=exception", + connectClusterId, connectorName, configs, operator, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + @Override + public Result resumeConnector(Long connectClusterId, String connectorName, String operator) { + try { + ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); + if (ValidateUtils.isNull(connectCluster)) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); + } + + restTool.putJsonForObject( + connectCluster.getSuitableRequestUrl() + String.format(RESUME_CONNECTOR_URI, connectorName), + new HashMap<>(), + String.class + ); + + this.updateStatus(connectCluster, connectClusterId, connectorName); + + opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( + operator, + OperationEnum.ENABLE.getDesc(), + ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), + MsgConstant.getConnectorBizStr(connectClusterId, connectorName), + "" + )); + + return Result.buildSuc(); + } catch (Exception e) { + LOGGER.error( + "class=ConnectorServiceImpl||method=resumeConnector||connectClusterId={}||errMsg=exception", + connectClusterId, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + @Override + public Result restartConnector(Long connectClusterId, String connectorName, String operator) { + try { + ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); + if (ValidateUtils.isNull(connectCluster)) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); + } + + restTool.postObjectWithJsonContent( + connectCluster.getSuitableRequestUrl() + String.format(RESTART_CONNECTOR_URI, connectorName), + new HashMap<>(), + String.class + ); + + this.updateStatus(connectCluster, connectClusterId, connectorName); + + opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( + operator, + OperationEnum.RESTART.getDesc(), + ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), + MsgConstant.getConnectorBizStr(connectClusterId, connectorName), + "" + )); + + return Result.buildSuc(); + } catch (Exception e) { + LOGGER.error( + "method=restartConnector||connectClusterId={}||errMsg=exception", + connectClusterId, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + @Override + public Result stopConnector(Long connectClusterId, String connectorName, String operator) { + try { + ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); + if (ValidateUtils.isNull(connectCluster)) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); + } + + restTool.putJsonForObject( + connectCluster.getSuitableRequestUrl() + String.format(PAUSE_CONNECTOR_URI, connectorName), + new HashMap<>(), + String.class + ); + + this.updateStatus(connectCluster, connectClusterId, connectorName); + + opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( + operator, + OperationEnum.DISABLE.getDesc(), + ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), + MsgConstant.getConnectorBizStr(connectClusterId, connectorName), + "" + )); + + return Result.buildSuc(); + } catch (Exception e) { + LOGGER.error( + "method=stopConnector||connectClusterId={}||errMsg=exception", + connectClusterId, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + @Override + public Result deleteConnector(Long connectClusterId, String connectorName, String operator) { + try { + ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); + if (ValidateUtils.isNull(connectCluster)) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); + } + + restTool.deleteWithParamsAndHeader( + connectCluster.getSuitableRequestUrl() + String.format(DELETE_CONNECTOR_URI, connectorName), + new HashMap<>(), + new HashMap<>(), + String.class + ); + + opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( + operator, + OperationEnum.DELETE.getDesc(), + ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), + MsgConstant.getConnectorBizStr(connectClusterId, connectorName), + "" + )); + + this.deleteConnectorInDB(connectClusterId, connectorName); + + return Result.buildSuc(); + } catch (Exception e) { + LOGGER.error( + "method=deleteConnector||connectClusterId={}||errMsg=exception", + connectClusterId, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + @Override + public Result updateConnectorConfig(Long connectClusterId, String connectorName, Properties configs, String operator) { + try { + ConnectCluster connectCluster = connectClusterService.getById(connectClusterId); + if (ValidateUtils.isNull(connectCluster)) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getConnectClusterNotExist(connectClusterId)); + } + + ConnectorInfo connectorInfo = restTool.putJsonForObject( + connectCluster.getSuitableRequestUrl() + String.format(UPDATE_CONNECTOR_CONFIG_URI, connectorName), + configs, + ConnectorInfo.class + ); + + this.updateStatus(connectCluster, connectClusterId, connectorName); + + opLogWrapService.saveOplogAndIgnoreException(new OplogDTO( + operator, + OperationEnum.EDIT.getDesc(), + ModuleEnum.KAFKA_CONNECT_CONNECTOR.getDesc(), + MsgConstant.getConnectorBizStr(connectClusterId, connectorName), + ConvertUtil.obj2Json(configs) + )); + + return Result.buildSuc(); + } catch (Exception e) { + LOGGER.error( + "method=updateConnectorConfig||connectClusterId={}||errMsg=exception", + connectClusterId, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + @Override + public void addNewToDB(KSConnector connector) { + try { + connectorDAO.insert(ConvertUtil.obj2Obj(connector, ConnectorPO.class)); + } catch (DuplicateKeyException dke) { + // ignore + } + } + + /**************************************************** private method ****************************************************/ + private int deleteConnectorInDB(Long connectClusterId, String connectorName) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ConnectorPO::getConnectClusterId, connectClusterId); + lambdaQueryWrapper.eq(ConnectorPO::getConnectorName, connectorName); + + return connectorDAO.delete(lambdaQueryWrapper); + } + + private Result getConnectorStateInfoFromCluster(ConnectCluster connectCluster, String connectorName) { + try { + KSConnectorStateInfo connectorStateInfo = restTool.getForObject( + connectCluster.getSuitableRequestUrl() + String.format(GET_CONNECTOR_STATUS_URI, connectorName), + new HashMap<>(), + KSConnectorStateInfo.class + ); + + return Result.buildSuc(connectorStateInfo); + } catch (Exception e) { + LOGGER.error( + "method=getConnectorStateInfoFromCluster||connectClusterId={}||connectorName={}||errMsg=exception", + connectCluster.getId(), connectorName, e + ); + + return Result.buildFromRSAndMsg(ResultStatus.KAFKA_CONNECTOR_READ_FAILED, e.getMessage()); + } + } + + private void updateStatus(ConnectCluster connectCluster, Long connectClusterId, String connectorName) { + try { + // 延迟3秒 + BackoffUtils.backoff(2000); + + Result stateInfoResult = this.getConnectorStateInfoFromCluster(connectCluster, connectorName); + if (stateInfoResult.failed()) { + return; + } + + ConnectorPO po = new ConnectorPO(); + po.setConnectClusterId(connectClusterId); + po.setConnectorName(connectorName); + po.setState(stateInfoResult.getData().getConnector().getState()); + + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ConnectorPO::getConnectClusterId, connectClusterId); + lambdaQueryWrapper.eq(ConnectorPO::getConnectorName, connectorName); + + connectorDAO.update(po, lambdaQueryWrapper); + } catch (Exception e) { + LOGGER.error( + "method=updateStatus||connectClusterId={}||connectorName={}||errMsg=exception", + connectClusterId, connectorName, e + ); + } + } +} diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java index b0a7d7b56..5bfb85baa 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/group/impl/GroupServiceImpl.java @@ -78,7 +78,7 @@ public List listGroupsFromKafka(ClusterPhy clusterPhy) throws AdminOpera } props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, clusterPhy.getBootstrapServers()); - props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("KSPartialAdminClient||clusterPhyId=%d", clusterPhy.getId())); + props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("KSPartialAdminClient||clusterPhyId=%d||timestamp=%d", clusterPhy.getId(), System.currentTimeMillis())); adminClient = KSPartialKafkaAdminClient.create(props); KSListGroupsResult listConsumerGroupsResult = adminClient.listConsumerGroups( @@ -179,7 +179,7 @@ public KSGroupDescription getGroupDescriptionFromKafka(ClusterPhy clusterPhy, St } props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, clusterPhy.getBootstrapServers()); - props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("KSPartialAdminClient||clusterPhyId=%d", clusterPhy.getId())); + props.put(AdminClientConfig.CLIENT_ID_CONFIG, String.format("KSPartialAdminClient||clusterPhyId=%d||timestamp=%d", clusterPhy.getId(), System.currentTimeMillis())); adminClient = KSPartialKafkaAdminClient.create(props); diff --git a/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/connect/KafkaConnectorController.java b/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/connect/KafkaConnectorController.java index b03ca7cce..32d76be3b 100644 --- a/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/connect/KafkaConnectorController.java +++ b/km-rest/src/main/java/com/xiaojukeji/know/streaming/km/rest/api/v3/connect/KafkaConnectorController.java @@ -15,7 +15,7 @@ import com.xiaojukeji.know.streaming.km.common.enums.connect.ConnectActionEnum; import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; -import com.xiaojukeji.know.streaming.km.core.service.connect.connector.ConnectorService; +import com.xiaojukeji.know.streaming.km.core.service.connect.connector.OpConnectorService; import com.xiaojukeji.know.streaming.km.core.service.connect.plugin.PluginService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -31,9 +31,8 @@ @RestController @RequestMapping(ApiPrefix.API_V3_CONNECT_PREFIX) public class KafkaConnectorController { - @Autowired - private ConnectorService connectorService; + private OpConnectorService opConnectorService; @Autowired private ConnectorManager connectorManager; @@ -56,7 +55,7 @@ public Result createConnector(@Validated @RequestBody ConnectorCreateDTO d @DeleteMapping(value ="connectors") @ResponseBody public Result deleteConnectors(@Validated @RequestBody ConnectorDeleteDTO dto) { - return connectorService.deleteConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); + return opConnectorService.deleteConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); } @ApiOperation(value = "操作Connector", notes = "") @@ -64,11 +63,11 @@ public Result deleteConnectors(@Validated @RequestBody ConnectorDeleteDTO @ResponseBody public Result operateConnectors(@Validated @RequestBody ConnectorActionDTO dto) { if (ConnectActionEnum.RESTART.getValue().equals(dto.getAction())) { - return connectorService.restartConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); + return opConnectorService.restartConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); } else if (ConnectActionEnum.STOP.getValue().equals(dto.getAction())) { - return connectorService.stopConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); + return opConnectorService.stopConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); } else if (ConnectActionEnum.RESUME.getValue().equals(dto.getAction())) { - return connectorService.resumeConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); + return opConnectorService.resumeConnector(dto.getConnectClusterId(), dto.getConnectorName(), HttpRequestUtil.getOperator()); } return Result.buildFailure(ResultStatus.PARAM_ILLEGAL); diff --git a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/connect/metadata/SyncConnectorTask.java b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/connect/metadata/SyncConnectorTask.java index 00e584251..799d7223d 100644 --- a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/connect/metadata/SyncConnectorTask.java +++ b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/connect/metadata/SyncConnectorTask.java @@ -3,17 +3,15 @@ import com.didiglobal.logi.job.annotation.Task; import com.didiglobal.logi.job.common.TaskResult; import com.didiglobal.logi.job.core.consensual.ConsensualEnum; -import com.didiglobal.logi.log.ILog; -import com.didiglobal.logi.log.LogFactory; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectCluster; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnector; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; +import com.xiaojukeji.know.streaming.km.common.utils.Tuple; import com.xiaojukeji.know.streaming.km.core.service.connect.connector.ConnectorService; import org.springframework.beans.factory.annotation.Autowired; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; +import java.util.Set; @Task(name = "SyncConnectorTask", @@ -23,40 +21,21 @@ consensual = ConsensualEnum.BROADCAST, timeout = 2 * 60) public class SyncConnectorTask extends AbstractAsyncMetadataDispatchTask { - private static final ILog LOGGER = LogFactory.getLog(SyncConnectorTask.class); - @Autowired private ConnectorService connectorService; + @Override public TaskResult processClusterTask(ConnectCluster connectCluster, long triggerTimeUnitMs) { - Result> nameListResult = connectorService.listConnectorsFromCluster(connectCluster.getId()); - if (nameListResult.failed()) { - return TaskResult.FAIL; - } - - boolean allSuccess = true; - - List connectorList = new ArrayList<>(); - for (String connectorName: nameListResult.getData()) { - Result ksConnectorResult = connectorService.getAllConnectorInfoFromCluster(connectCluster.getId(), connectorName); - if (ksConnectorResult.failed()) { - LOGGER.error( - "method=processClusterTask||connectClusterId={}||connectorName={}||result={}", - connectCluster.getId(), connectorName, ksConnectorResult - ); - - allSuccess = false; - continue; - } - - connectorList.add(ksConnectorResult.getData()); + // 获取信息 + Result, List>> dataResult = connectorService.getDataFromKafka(connectCluster); + if (dataResult.failed()) { + return new TaskResult(TaskResult.FAIL_CODE, dataResult.getMessage()); } - //mm2相关信息的添加 - connectorService.completeMirrorMakerInfo(connectCluster, connectorList); - - connectorService.batchReplace(connectCluster.getKafkaClusterPhyId(), connectCluster.getId(), connectorList, new HashSet<>(nameListResult.getData())); + // 更新到DB + connectorService.writeToDB( connectCluster.getId(), dataResult.getData().v1(), dataResult.getData().v2()); - return allSuccess? TaskResult.SUCCESS: TaskResult.FAIL; + // 返回结果 + return dataResult.getData().v1().size() == dataResult.getData().v2().size()? TaskResult.SUCCESS: TaskResult.FAIL; } } From a7309612d56be26bdcb4ad1f186bd5b5b836a130 Mon Sep 17 00:00:00 2001 From: EricZeng Date: Tue, 15 Aug 2023 18:46:41 +0800 Subject: [PATCH 09/48] =?UTF-8?q?[Optimize]=E7=BB=9F=E4=B8=80DB=E5=85=83?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=9B=B4=E6=96=B0=E6=A0=BC=E5=BC=8F-Part2=20?= =?UTF-8?q?(#1127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、KafkaMetaService修改为MetaService并移动到Core层; 2、修改ZK、KafkaACL的格式; --- .../km/core/service/acl/KafkaAclService.java | 11 +-- .../core/service/acl/OpKafkaAclService.java | 13 --- .../service/acl/impl/KafkaAclServiceImpl.java | 90 ++++++++++++------- .../acl/impl/OpKafkaAclServiceImpl.java | 37 -------- .../connect/connector/ConnectorService.java | 4 +- .../km/core/service/meta/MetaDataService.java | 19 ++-- .../service/zookeeper/ZookeeperService.java | 12 +-- .../zookeeper/impl/ZookeeperServiceImpl.java | 42 +++++---- .../task/kafka/metadata/SyncKafkaAclTask.java | 24 +---- .../kafka/metadata/SyncZookeeperTask.java | 15 +--- 10 files changed, 108 insertions(+), 159 deletions(-) rename km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java => km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/meta/MetaDataService.java (65%) diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/KafkaAclService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/KafkaAclService.java index 3e50771b5..9e9735a96 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/KafkaAclService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/KafkaAclService.java @@ -1,15 +1,13 @@ package com.xiaojukeji.know.streaming.km.core.service.acl; -import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.po.KafkaAclPO; +import com.xiaojukeji.know.streaming.km.core.service.meta.MetaDataService; import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.resource.ResourceType; import java.util.List; -public interface KafkaAclService { - Result> getAclFromKafka(Long clusterPhyId); - +public interface KafkaAclService extends MetaDataService { List getKafkaAclFromDB(Long clusterPhyId); Integer countKafkaAclFromDB(Long clusterPhyId); @@ -17,10 +15,5 @@ public interface KafkaAclService { Integer countResTypeAndDistinctFromDB(Long clusterPhyId, ResourceType resourceType); Integer countKafkaUserAndDistinctFromDB(Long clusterPhyId); - - List getKafkaResTypeAclFromDB(Long clusterPhyId, Integer resType); - List getTopicAclFromDB(Long clusterPhyId, String topicName); - - List getGroupAclFromDB(Long clusterPhyId, String groupName); } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/OpKafkaAclService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/OpKafkaAclService.java index 7dd59c754..f6129326b 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/OpKafkaAclService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/OpKafkaAclService.java @@ -3,10 +3,6 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.param.acl.ACLAtomParam; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.po.KafkaAclPO; -import org.apache.kafka.common.resource.ResourceType; - -import java.util.Date; -import java.util.List; public interface OpKafkaAclService { /** @@ -19,14 +15,5 @@ public interface OpKafkaAclService { */ Result deleteKafkaAcl(ACLAtomParam aclAtomParam, String operator); - /** - * 删除ACL - */ - Result deleteKafkaAclByResName(ResourceType resourceType, String resourceName, String operator); - Result insertAndIgnoreDuplicate(KafkaAclPO kafkaAclPO); - - void batchUpdateAcls(Long clusterPhyId, List poList); - - int deleteByUpdateTimeBeforeInDB(Long clusterPhyId, Date beforeTime); } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/KafkaAclServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/KafkaAclServiceImpl.java index 8f1473cda..65258044a 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/KafkaAclServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/KafkaAclServiceImpl.java @@ -11,6 +11,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.po.KafkaAclPO; import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; import com.xiaojukeji.know.streaming.km.common.constant.KafkaConstant; +import com.xiaojukeji.know.streaming.km.common.converter.KafkaAclConverter; import com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterAuthTypeEnum; import com.xiaojukeji.know.streaming.km.common.enums.version.VersionItemTypeEnum; import com.xiaojukeji.know.streaming.km.common.exception.VCHandlerNotExistException; @@ -18,8 +19,6 @@ import com.xiaojukeji.know.streaming.km.core.service.acl.KafkaAclService; import com.xiaojukeji.know.streaming.km.core.service.cluster.ClusterPhyService; import com.xiaojukeji.know.streaming.km.core.service.version.BaseKafkaVersionControlService; -import com.xiaojukeji.know.streaming.km.core.service.version.BaseVersionControlService; -import com.xiaojukeji.know.streaming.km.persistence.cache.LoadedClusterPhyCache; import com.xiaojukeji.know.streaming.km.persistence.kafka.KafkaAdminClient; import com.xiaojukeji.know.streaming.km.persistence.kafka.KafkaAdminZKClient; import com.xiaojukeji.know.streaming.km.persistence.mysql.KafkaAclDAO; @@ -36,11 +35,13 @@ import org.apache.kafka.common.security.auth.KafkaPrincipal; import org.apache.kafka.common.utils.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import scala.jdk.javaapi.CollectionConverters; @@ -77,18 +78,49 @@ private void init() { } @Override - public Result> getAclFromKafka(Long clusterPhyId) { - if (LoadedClusterPhyCache.getByPhyId(clusterPhyId) == null) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getClusterPhyNotExist(clusterPhyId)); - } - + public Result> getDataFromKafka(ClusterPhy clusterPhy) { try { - return (Result>) versionControlService.doHandler(getVersionItemType(), getMethodName(clusterPhyId, ACL_GET_FROM_KAFKA), new ClusterPhyParam(clusterPhyId)); + Result> dataResult = (Result>) versionControlService.doHandler(getVersionItemType(), getMethodName(clusterPhy.getId(), ACL_GET_FROM_KAFKA), new ClusterPhyParam(clusterPhy.getId())); + if (dataResult.failed()) { + Result.buildFromIgnoreData(dataResult); + } + + return Result.buildSuc(dataResult.getData()); } catch (VCHandlerNotExistException e) { return Result.buildFailure(e.getResultStatus()); } } + @Override + public void writeToDB(Long clusterPhyId, List dataList) { + Map dbPOMap = this.getKafkaAclFromDB(clusterPhyId).stream().collect(Collectors.toMap(KafkaAclPO::getUniqueField, Function.identity())); + + long now = System.currentTimeMillis(); + for (AclBinding aclBinding: dataList) { + KafkaAclPO newPO = KafkaAclConverter.convert2KafkaAclPO(clusterPhyId, aclBinding, now); + KafkaAclPO oldPO = dbPOMap.remove(newPO.getUniqueField()); + if (oldPO == null) { + // 新增的ACL + this.insertAndIgnoreDuplicate(newPO); + } + + // 不需要update + } + + // 删除已经不存在的 + for (KafkaAclPO dbPO: dbPOMap.values()) { + kafkaAclDAO.deleteById(dbPO); + } + } + + @Override + public int deleteInDBByKafkaClusterId(Long clusterPhyId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(KafkaAclPO::getClusterPhyId, clusterPhyId); + + return kafkaAclDAO.delete(lambdaQueryWrapper); + } + @Override public List getKafkaAclFromDB(Long clusterPhyId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); @@ -116,7 +148,7 @@ public Integer countResTypeAndDistinctFromDB(Long clusterPhyId, ResourceType res return 0; } - return (int)poList.stream().map(elem -> elem.getResourceName()).distinct().count(); + return (int)poList.stream().map(KafkaAclPO::getResourceName).distinct().count(); } @Override @@ -130,15 +162,7 @@ public Integer countKafkaUserAndDistinctFromDB(Long clusterPhyId) { return 0; } - return (int)poList.stream().map(elem -> elem.getPrincipal()).distinct().count(); - } - - @Override - public List getKafkaResTypeAclFromDB(Long clusterPhyId, Integer resType) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(KafkaAclPO::getClusterPhyId, clusterPhyId); - queryWrapper.eq(KafkaAclPO::getResourceType, resType); - return kafkaAclDAO.selectList(queryWrapper); + return (int)poList.stream().map(KafkaAclPO::getPrincipal).distinct().count(); } @Override @@ -152,15 +176,6 @@ public List getTopicAclFromDB(Long clusterPhyId, String topicName) { return kafkaAclDAO.selectList(queryWrapper); } - @Override - public List getGroupAclFromDB(Long clusterPhyId, String groupName) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(KafkaAclPO::getClusterPhyId, clusterPhyId); - queryWrapper.eq(KafkaAclPO::getResourceType, ResourceType.GROUP.code()); - queryWrapper.eq(KafkaAclPO::getResourceName, groupName); - return kafkaAclDAO.selectList(queryWrapper); - } - /**************************************************** private method ****************************************************/ private Result> getAclByZKClient(VersionItemParam itemParam){ @@ -170,7 +185,7 @@ private Result> getAclByZKClient(VersionItemParam itemParam){ for (ZkAclStore store: CollectionConverters.asJava(ZkAclStore.stores())) { Result> rl = this.getSpecifiedTypeAclByZKClient(param.getClusterPhyId(), store.patternType()); if (rl.failed()) { - return rl; + return Result.buildFromIgnoreData(rl); } aclList.addAll(rl.getData()); @@ -229,4 +244,19 @@ private Result> getSpecifiedTypeAclByZKClient(Long clusterPhyId return Result.buildSuc(kafkaAclList); } + + private Result insertAndIgnoreDuplicate(KafkaAclPO kafkaAclPO) { + try { + kafkaAclDAO.insert(kafkaAclPO); + + return Result.buildSuc(); + } catch (DuplicateKeyException dke) { + // 直接写入,如果出现key冲突则直接忽略,因为key冲突时,表示该数据已完整存在,不需要替换任何数据 + return Result.buildSuc(); + } catch (Exception e) { + log.error("method=insertAndIgnoreDuplicate||kafkaAclPO={}||errMsg=exception", kafkaAclPO, e); + + return Result.buildFromRSAndMsg(ResultStatus.MYSQL_OPERATE_FAILED, e.getMessage()); + } + } } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/OpKafkaAclServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/OpKafkaAclServiceImpl.java index a8fab1f1b..c3915cded 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/OpKafkaAclServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/acl/impl/OpKafkaAclServiceImpl.java @@ -20,7 +20,6 @@ import com.xiaojukeji.know.streaming.km.core.service.acl.OpKafkaAclService; import com.xiaojukeji.know.streaming.km.core.service.oprecord.OpLogWrapService; import com.xiaojukeji.know.streaming.km.core.service.version.BaseKafkaVersionControlService; -import com.xiaojukeji.know.streaming.km.core.service.version.BaseVersionControlService; import com.xiaojukeji.know.streaming.km.persistence.kafka.KafkaAdminClient; import com.xiaojukeji.know.streaming.km.persistence.kafka.KafkaAdminZKClient; import com.xiaojukeji.know.streaming.km.persistence.mysql.KafkaAclDAO; @@ -32,7 +31,6 @@ import org.apache.kafka.common.acl.*; import org.apache.kafka.common.resource.ResourcePattern; import org.apache.kafka.common.resource.ResourcePatternFilter; -import org.apache.kafka.common.resource.ResourceType; import org.apache.kafka.common.security.auth.KafkaPrincipal; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; @@ -41,8 +39,6 @@ import javax.annotation.PostConstruct; import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; import static com.xiaojukeji.know.streaming.km.common.enums.version.VersionEnum.*; @@ -169,11 +165,6 @@ public Result deleteKafkaAcl(ACLAtomParam aclAtomParam, String operator) { return rv; } - @Override - public Result deleteKafkaAclByResName(ResourceType resourceType, String resourceName, String operator) { - return Result.buildSuc(); - } - @Override public Result insertAndIgnoreDuplicate(KafkaAclPO kafkaAclPO) { try { @@ -190,34 +181,6 @@ public Result insertAndIgnoreDuplicate(KafkaAclPO kafkaAclPO) { } } - @Override - public void batchUpdateAcls(Long clusterPhyId, List poList) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(KafkaAclPO::getClusterPhyId, clusterPhyId); - - Map dbPOMap = kafkaAclDAO.selectList(lambdaQueryWrapper).stream().collect(Collectors.toMap(KafkaAclPO::getUniqueField, Function.identity())); - for (KafkaAclPO po: poList) { - KafkaAclPO dbPO = dbPOMap.remove(po.getUniqueField()); - if (dbPO == null) { - // 新增的ACL - this.insertAndIgnoreDuplicate(po); - } - } - - // 删除已经不存在的 - for (KafkaAclPO dbPO: dbPOMap.values()) { - kafkaAclDAO.deleteById(dbPO); - } - } - - @Override - public int deleteByUpdateTimeBeforeInDB(Long clusterPhyId, Date beforeTime) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(KafkaAclPO::getClusterPhyId, clusterPhyId); - lambdaQueryWrapper.le(KafkaAclPO::getUpdateTime, beforeTime); - return kafkaAclDAO.delete(lambdaQueryWrapper); - } - /**************************************************** private method ****************************************************/ private Result deleteInDB(KafkaAclPO kafkaAclPO) { diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java index 7a85ffd28..05fe2cf95 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/connector/ConnectorService.java @@ -4,7 +4,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnector; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorInfo; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.connector.KSConnectorStateInfo; -import com.xiaojukeji.know.streaming.km.common.bean.entity.meta.KafkaMetaService; +import com.xiaojukeji.know.streaming.km.core.service.meta.MetaDataService; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.po.connect.ConnectorPO; import com.xiaojukeji.know.streaming.km.common.enums.connect.ConnectorTypeEnum; @@ -14,7 +14,7 @@ /** * 查看Connector */ -public interface ConnectorService extends KafkaMetaService { +public interface ConnectorService extends MetaDataService { /** * 获取所有的连接器名称列表 */ diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/meta/MetaDataService.java similarity index 65% rename from km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java rename to km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/meta/MetaDataService.java index d0307afc2..b1c34dbf6 100644 --- a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/entity/meta/KafkaMetaService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/meta/MetaDataService.java @@ -1,4 +1,4 @@ -package com.xiaojukeji.know.streaming.km.common.bean.entity.meta; +package com.xiaojukeji.know.streaming.km.core.service.meta; import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectCluster; @@ -13,7 +13,7 @@ /** * Kafka元信息服务接口 */ -public interface KafkaMetaService { +public interface MetaDataService { /** * 从Kafka中获取数据 * @param connectCluster connect集群 @@ -26,19 +26,26 @@ public interface KafkaMetaService { * @param clusterPhy kafka集群 * @return 全部资源集合, 成功的资源列表 */ - default Result, List>> getDataFromKafka(ClusterPhy clusterPhy) { return Result.buildSuc(new Tuple<>(new HashSet<>(), new ArrayList<>())); } + default Result> getDataFromKafka(ClusterPhy clusterPhy) { return Result.buildSuc(new ArrayList<>()); } /** * 元信息同步至DB中 * @param clusterId 集群ID - * @param fullNameSet 全部资源列表 + * @param fullResSet 全部资源列表 * @param dataList 成功的资源列表 */ - default void writeToDB(Long clusterId, Set fullNameSet, List dataList) {} + default void writeToDB(Long clusterId, Set fullResSet, List dataList) {} + + /** + * 元信息同步至DB中 + * @param clusterId 集群ID + * @param dataList 成功的资源列表 + */ + default void writeToDB(Long clusterId, List dataList) {} /** * 依据kafka集群ID删除数据 * @param clusterPhyId kafka集群ID */ - default int deleteInDBByKafkaClusterId(Long clusterPhyId) { return 0; } + int deleteInDBByKafkaClusterId(Long clusterPhyId); } diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/ZookeeperService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/ZookeeperService.java index 8d3a78b10..1d324928f 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/ZookeeperService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/ZookeeperService.java @@ -1,19 +1,11 @@ package com.xiaojukeji.know.streaming.km.core.service.zookeeper; -import com.xiaojukeji.know.streaming.km.common.bean.entity.config.ZKConfig; -import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.entity.zookeeper.ZookeeperInfo; +import com.xiaojukeji.know.streaming.km.core.service.meta.MetaDataService; import java.util.List; -public interface ZookeeperService { - /** - * 从ZK集群中获取ZK信息 - */ - Result> listFromZookeeper(Long clusterPhyId, String zookeeperAddress, ZKConfig zkConfig); - - void batchReplaceDataInDB(Long clusterPhyId, List infoList); - +public interface ZookeeperService extends MetaDataService { List listFromDBByCluster(Long clusterPhyId); /** diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/impl/ZookeeperServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/impl/ZookeeperServiceImpl.java index 8b0d63d1f..dc2f58d24 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/impl/ZookeeperServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/zookeeper/impl/ZookeeperServiceImpl.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.didiglobal.logi.log.ILog; import com.didiglobal.logi.log.LogFactory; +import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy; import com.xiaojukeji.know.streaming.km.common.bean.entity.config.ZKConfig; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.ResultStatus; @@ -22,10 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; @Service public class ZookeeperServiceImpl implements ZookeeperService { @@ -35,14 +34,14 @@ public class ZookeeperServiceImpl implements ZookeeperService { private ZookeeperDAO zookeeperDAO; @Override - public Result> listFromZookeeper(Long clusterPhyId, String zookeeperAddress, ZKConfig zkConfig) { + public Result> getDataFromKafka(ClusterPhy clusterPhy) { List> addressList = null; try { - addressList = ZookeeperUtils.connectStringParser(zookeeperAddress); + addressList = ZookeeperUtils.connectStringParser(clusterPhy.getZookeeper()); } catch (Exception e) { LOGGER.error( - "method=listFromZookeeperCluster||clusterPhyId={}||zookeeperAddress={}||errMsg=exception!", - clusterPhyId, zookeeperAddress, e + "method=getDataFromKafka||clusterPhyId={}||zookeeperAddress={}||errMsg=exception!", + clusterPhy.getId(), clusterPhy.getZookeeper(), e ); return Result.buildFromRSAndMsg(ResultStatus.PARAM_ILLEGAL, e.getMessage()); @@ -51,24 +50,25 @@ public Result> listFromZookeeper(Long clusterPhyId, String z List aliveZKList = new ArrayList<>(); for (Tuple hostPort: addressList) { aliveZKList.add(this.getFromZookeeperCluster( - clusterPhyId, + clusterPhy.getId(), hostPort.getV1(), hostPort.getV2(), - zkConfig + ConvertUtil.str2ObjByJson(clusterPhy.getZkProperties(), ZKConfig.class) )); } + return Result.buildSuc(aliveZKList); } @Override - public void batchReplaceDataInDB(Long clusterPhyId, List infoList) { + public void writeToDB(Long clusterId, List dataList) { // DB 中的信息 - List dbInfoList = this.listRawFromDBByCluster(clusterPhyId); - Map dbMap = new HashMap<>(); - dbInfoList.stream().forEach(elem -> dbMap.put(elem.getHost() + elem.getPort(), elem)); + Map dbMap = this.listRawFromDBByCluster(clusterId) + .stream() + .collect(Collectors.toMap(elem -> elem.getHost() + elem.getPort(), elem -> elem, (oldValue, newValue) -> newValue)); // 新获取到的信息 - List newInfoList = ConvertUtil.list2List(infoList, ZookeeperInfoPO.class); + List newInfoList = ConvertUtil.list2List(dataList, ZookeeperInfoPO.class); for (ZookeeperInfoPO newInfo: newInfoList) { try { ZookeeperInfoPO oldInfo = dbMap.remove(newInfo.getHost() + newInfo.getPort()); @@ -87,7 +87,7 @@ public void batchReplaceDataInDB(Long clusterPhyId, List infoList zookeeperDAO.updateById(newInfo); } } catch (Exception e) { - LOGGER.error("method=batchReplaceDataInDB||clusterPhyId={}||newInfo={}||errMsg=exception", clusterPhyId, newInfo, e); + LOGGER.error("method=writeToDB||clusterPhyId={}||newInfo={}||errMsg=exception", clusterId, newInfo, e); } } @@ -96,11 +96,19 @@ public void batchReplaceDataInDB(Long clusterPhyId, List infoList try { zookeeperDAO.deleteById(entry.getValue().getId()); } catch (Exception e) { - LOGGER.error("method=batchReplaceDataInDB||clusterPhyId={}||expiredInfo={}||errMsg=exception", clusterPhyId, entry.getValue(), e); + LOGGER.error("method=writeToDB||clusterPhyId={}||expiredInfo={}||errMsg=exception", clusterId, entry.getValue(), e); } }); } + @Override + public int deleteInDBByKafkaClusterId(Long clusterPhyId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ZookeeperInfoPO::getClusterPhyId, clusterPhyId); + + return zookeeperDAO.delete(lambdaQueryWrapper); + } + @Override public List listFromDBByCluster(Long clusterPhyId) { return ConvertUtil.list2List(this.listRawFromDBByCluster(clusterPhyId), ZookeeperInfo.class); diff --git a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncKafkaAclTask.java b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncKafkaAclTask.java index 0dd5b8f7f..d0b4f3bac 100644 --- a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncKafkaAclTask.java +++ b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncKafkaAclTask.java @@ -3,19 +3,13 @@ import com.didiglobal.logi.job.annotation.Task; import com.didiglobal.logi.job.common.TaskResult; import com.didiglobal.logi.job.core.consensual.ConsensualEnum; -import com.didiglobal.logi.log.ILog; -import com.didiglobal.logi.log.LogFactory; import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; -import com.xiaojukeji.know.streaming.km.common.bean.po.KafkaAclPO; -import com.xiaojukeji.know.streaming.km.common.converter.KafkaAclConverter; import com.xiaojukeji.know.streaming.km.core.service.acl.KafkaAclService; -import com.xiaojukeji.know.streaming.km.core.service.acl.OpKafkaAclService; import org.apache.kafka.common.acl.AclBinding; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; -import java.util.stream.Collectors; @Task(name = "SyncKafkaAclTask", description = "KafkaAcl信息同步到DB", @@ -24,32 +18,18 @@ consensual = ConsensualEnum.BROADCAST, timeout = 2 * 60) public class SyncKafkaAclTask extends AbstractAsyncMetadataDispatchTask { - private static final ILog log = LogFactory.getLog(SyncKafkaAclTask.class); - @Autowired private KafkaAclService kafkaAclService; - @Autowired - private OpKafkaAclService opKafkaAclService; - @Override public TaskResult processClusterTask(ClusterPhy clusterPhy, long triggerTimeUnitMs) { - Result> aclBindingListResult = kafkaAclService.getAclFromKafka(clusterPhy.getId()); + Result> aclBindingListResult = kafkaAclService.getDataFromKafka(clusterPhy); if (aclBindingListResult.failed()) { return TaskResult.FAIL; } - if (!aclBindingListResult.hasData()) { - return TaskResult.SUCCESS; - } - - // 更新DB数据 - List poList = aclBindingListResult.getData() - .stream() - .map(elem -> KafkaAclConverter.convert2KafkaAclPO(clusterPhy.getId(), elem, triggerTimeUnitMs)) - .collect(Collectors.toList()); + kafkaAclService.writeToDB(clusterPhy.getId(), aclBindingListResult.getData()); - opKafkaAclService.batchUpdateAcls(clusterPhy.getId(), poList); return TaskResult.SUCCESS; } } diff --git a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncZookeeperTask.java b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncZookeeperTask.java index e87f2bf18..4ce988d38 100644 --- a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncZookeeperTask.java +++ b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/kafka/metadata/SyncZookeeperTask.java @@ -3,12 +3,8 @@ import com.didiglobal.logi.job.annotation.Task; import com.didiglobal.logi.job.common.TaskResult; import com.didiglobal.logi.job.core.consensual.ConsensualEnum; -import com.didiglobal.logi.log.ILog; -import com.didiglobal.logi.log.LogFactory; import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy; -import com.xiaojukeji.know.streaming.km.common.bean.entity.config.ZKConfig; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; -import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; import com.xiaojukeji.know.streaming.km.common.bean.entity.zookeeper.ZookeeperInfo; import com.xiaojukeji.know.streaming.km.core.service.zookeeper.ZookeeperService; import org.springframework.beans.factory.annotation.Autowired; @@ -23,24 +19,17 @@ consensual = ConsensualEnum.BROADCAST, timeout = 2 * 60) public class SyncZookeeperTask extends AbstractAsyncMetadataDispatchTask { - private static final ILog log = LogFactory.getLog(SyncZookeeperTask.class); - @Autowired private ZookeeperService zookeeperService; @Override public TaskResult processClusterTask(ClusterPhy clusterPhy, long triggerTimeUnitMs) { - Result> infoResult = zookeeperService.listFromZookeeper( - clusterPhy.getId(), - clusterPhy.getZookeeper(), - ConvertUtil.str2ObjByJson(clusterPhy.getZkProperties(), ZKConfig.class) - ); - + Result> infoResult = zookeeperService.getDataFromKafka(clusterPhy); if (infoResult.failed()) { return new TaskResult(TaskResult.FAIL_CODE, infoResult.getMessage()); } - zookeeperService.batchReplaceDataInDB(clusterPhy.getId(), infoResult.getData()); + zookeeperService.writeToDB(clusterPhy.getId(), infoResult.getData()); return TaskResult.SUCCESS; } From d1417bef8c39795910cda0e75f03b2224b6334ac Mon Sep 17 00:00:00 2001 From: EricZeng Date: Wed, 16 Aug 2023 10:54:58 +0800 Subject: [PATCH 10/48] =?UTF-8?q?[Bugfix]=E4=BF=AE=E5=A4=8D=E5=88=A0?= =?UTF-8?q?=E9=99=A4Kafka=E9=9B=86=E7=BE=A4=E5=90=8E=EF=BC=8CConnect?= =?UTF-8?q?=E9=9B=86=E7=BE=A4=E4=BB=BB=E5=8A=A1=E5=87=BA=E7=8E=B0NPE?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20(#1129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原因: 首先,删除Kafka集群后,没有将DB中的Connect集群进行删除。随后,进行Connect集群指标采集时,由于所在的Kafka集群已经不存在了。最终,导致NPE; 解决: 发布一个Kafka集群删除事件,触发MetaDataService子类,将其在DB中的数据进行删除。 遗留: 当前MetaDataService仅在部分元信息同步类中实现,导致当前DB中的脏数据清理不彻底,后续等MetaDataService在所有元信息同步类中实现后,便可彻底清理数据。 PS:当前修复已保证NPE问题不会再出现。 --- .../connect/ClusterPhyDeletedEvent.java | 16 ++++++ .../cluster/impl/ClusterPhyServiceImpl.java | 4 ++ .../cluster/ConnectClusterService.java | 4 +- .../impl/ConnectClusterServiceImpl.java | 8 +++ .../listener/TaskClusterDeletedListener.java | 53 +++++++++++++++++++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/event/cluster/connect/ClusterPhyDeletedEvent.java create mode 100644 km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/service/listener/TaskClusterDeletedListener.java diff --git a/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/event/cluster/connect/ClusterPhyDeletedEvent.java b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/event/cluster/connect/ClusterPhyDeletedEvent.java new file mode 100644 index 000000000..29e19bc6b --- /dev/null +++ b/km-common/src/main/java/com/xiaojukeji/know/streaming/km/common/bean/event/cluster/connect/ClusterPhyDeletedEvent.java @@ -0,0 +1,16 @@ +package com.xiaojukeji.know.streaming.km.common.bean.event.cluster.connect; + +import com.xiaojukeji.know.streaming.km.common.bean.event.cluster.ClusterPhyBaseEvent; +import lombok.Getter; + +/** + * 集群删除事件 + * @author zengqiao + * @date 23/08/15 + */ +@Getter +public class ClusterPhyDeletedEvent extends ClusterPhyBaseEvent { + public ClusterPhyDeletedEvent(Object source, Long clusterPhyId) { + super(source, clusterPhyId); + } +} diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/cluster/impl/ClusterPhyServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/cluster/impl/ClusterPhyServiceImpl.java index 43a0557cb..6f9c5cfa1 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/cluster/impl/ClusterPhyServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/cluster/impl/ClusterPhyServiceImpl.java @@ -8,6 +8,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.ResultStatus; import com.xiaojukeji.know.streaming.km.common.bean.event.cluster.ClusterPhyAddedEvent; +import com.xiaojukeji.know.streaming.km.common.bean.event.cluster.connect.ClusterPhyDeletedEvent; import com.xiaojukeji.know.streaming.km.common.bean.po.cluster.ClusterPhyPO; import com.xiaojukeji.know.streaming.km.common.component.SpringTool; import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; @@ -146,6 +147,9 @@ public Result removeClusterPhyById(Long clusterPhyId, String operator) { String.format("删除集群:%s",clusterPhy.toString())); opLogWrapService.saveOplogAndIgnoreException(oplogDTO); + // 发布删除集群事件 + SpringTool.publish(new ClusterPhyDeletedEvent(this, clusterPhyId)); + return Result.buildSuc(); } catch (Exception e) { log.error("method=removeClusterPhyById||clusterPhyId={}||operator={}||msg=remove cluster failed||errMsg=exception!", diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/ConnectClusterService.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/ConnectClusterService.java index e6ad39297..621a56430 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/ConnectClusterService.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/ConnectClusterService.java @@ -4,14 +4,16 @@ import com.xiaojukeji.know.streaming.km.common.bean.dto.connect.cluster.ConnectClusterDTO; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectCluster; import com.xiaojukeji.know.streaming.km.common.bean.entity.connect.ConnectClusterMetadata; +import com.xiaojukeji.know.streaming.km.common.bean.entity.kafka.KSGroupDescription; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; +import com.xiaojukeji.know.streaming.km.core.service.meta.MetaDataService; import java.util.List; /** * Connect-Cluster */ -public interface ConnectClusterService { +public interface ConnectClusterService extends MetaDataService { Long replaceAndReturnIdInDB(ConnectClusterMetadata metadata); List listByKafkaCluster(Long kafkaClusterPhyId); diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterServiceImpl.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterServiceImpl.java index 86879662d..c0908b333 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterServiceImpl.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/connect/cluster/impl/ConnectClusterServiceImpl.java @@ -38,6 +38,14 @@ public class ConnectClusterServiceImpl implements ConnectClusterService { @Autowired private OpLogWrapService opLogWrapService; + @Override + public int deleteInDBByKafkaClusterId(Long clusterPhyId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ConnectClusterPO::getKafkaClusterPhyId, clusterPhyId); + + return connectClusterDAO.deleteById(lambdaQueryWrapper); + } + @Override public Long replaceAndReturnIdInDB(ConnectClusterMetadata metadata) { ConnectClusterPO oldPO = this.getPOFromDB(metadata.getKafkaClusterPhyId(), metadata.getGroupName()); diff --git a/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/service/listener/TaskClusterDeletedListener.java b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/service/listener/TaskClusterDeletedListener.java new file mode 100644 index 000000000..b10d61be5 --- /dev/null +++ b/km-task/src/main/java/com/xiaojukeji/know/streaming/km/task/service/listener/TaskClusterDeletedListener.java @@ -0,0 +1,53 @@ +package com.xiaojukeji.know.streaming.km.task.service.listener; + +import com.didiglobal.logi.log.ILog; +import com.didiglobal.logi.log.LogFactory; +import com.xiaojukeji.know.streaming.km.common.bean.event.cluster.connect.ClusterPhyDeletedEvent; +import com.xiaojukeji.know.streaming.km.common.component.SpringTool; +import com.xiaojukeji.know.streaming.km.common.utils.BackoffUtils; +import com.xiaojukeji.know.streaming.km.common.utils.FutureUtil; +import com.xiaojukeji.know.streaming.km.core.service.meta.MetaDataService; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Service; + +@Service +public class TaskClusterDeletedListener implements ApplicationListener { + private static final ILog LOGGER = LogFactory.getLog(TaskClusterDeletedListener.class); + + @Override + public void onApplicationEvent(ClusterPhyDeletedEvent event) { + LOGGER.info("method=onApplicationEvent||clusterPhyId={}||msg=listened delete cluster", event.getClusterPhyId()); + + // 交由KS自定义的线程池,异步执行任务 + FutureUtil.quickStartupFutureUtil.submitTask( + () -> { + // 延迟60秒,避免正在运行的任务,将数据写入DB中 + BackoffUtils.backoff(60000); + + for (MetaDataService metaDataService: SpringTool.getBeansOfType(MetaDataService.class).values()) { + LOGGER.info( + "method=onApplicationEvent||clusterPhyId={}||className={}||msg=delete cluster data in db starting", + event.getClusterPhyId(), metaDataService.getClass().getSimpleName() + ); + + try { + // 删除数据 + metaDataService.deleteInDBByKafkaClusterId(event.getClusterPhyId()); + + LOGGER.info( + "method=onApplicationEvent||clusterPhyId={}||className={}||msg=delete cluster data in db finished", + event.getClusterPhyId(), metaDataService.getClass().getSimpleName() + ); + } catch (Exception e) { + LOGGER.error( + "method=onApplicationEvent||clusterPhyId={}||className={}||msg=delete cluster data in db failed||errMsg=exception", + event.getClusterPhyId(), metaDataService.getClass().getSimpleName(), e + ); + } + } + } + ); + + + } +} From ea0c744677d18ae0e4872e0781c95018b64681ba Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 10 Sep 2023 13:51:38 +0800 Subject: [PATCH 11/48] =?UTF-8?q?'[Feature]=E5=A2=9E=E5=8A=A0Truncate?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8A=9F=E8=83=BD(#1043)'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layout-clusters-fe/src/api/index.ts | 1 + .../src/pages/TopicList/index.tsx | 51 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) 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 7dadd9ec8..95b847491 100755 --- a/km-console/packages/layout-clusters-fe/src/api/index.ts +++ b/km-console/packages/layout-clusters-fe/src/api/index.ts @@ -108,6 +108,7 @@ const api = { getTopicState: (clusterPhyId: number, topicName: string) => getApi(`/clusters/${clusterPhyId}/topics/${topicName}/state`), getTopicMetadata: (clusterPhyId: number, topicName: string) => getApi(`/clusters/${clusterPhyId}/topics/${topicName}/metadata-combine-exist`), + deleteTopicData: () => getApi(`/topics/truncate-topic`), // 最新的指标值 getMetricPointsLatest: (clusterPhyId: number) => getApi(`/physical-clusters/${clusterPhyId}/latest-metrics`), diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx index 4c3f88573..9521e5c46 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx @@ -1,7 +1,22 @@ /* eslint-disable react/display-name */ import React, { useState, useEffect } from 'react'; import { useHistory, useParams } from 'react-router-dom'; -import { AppContainer, Input, ProTable, Select, Switch, Tooltip, Utils, Dropdown, Menu, Button, Divider, Tag } from 'knowdesign'; +import { + AppContainer, + Input, + ProTable, + Select, + Switch, + Tooltip, + Utils, + Dropdown, + Menu, + Button, + Divider, + Tag, + Popconfirm, + notification, +} from 'knowdesign'; import { IconFont } from '@knowdesign/icons'; import Create from './Create'; import './index.less'; @@ -85,6 +100,25 @@ const AutoPage = (props: any) => { setTopicListLoading(false); }); }; + const deleteTopicData = (record: any) => { + console.log(record, 'record'); + const params = { + clusterId: Number(routeParams.clusterId), + topicName: record.topicName, + }; + Utils.post(Api.deleteTopicData(), params).then((data: any) => { + if (data === null) { + notification.success({ + message: '清除数据成功', + }); + getTopicsList(); + } else { + notification.error({ + message: '清除数据失败', + }); + } + }); + }; useEffect(() => { getTopicsList(); }, [sortObj, showInternalTopics, searchKeywords, pageIndex, pageSize]); @@ -247,7 +281,7 @@ const AutoPage = (props: any) => { dataIndex: 'desc', key: 'desc', fixed: 'right', - width: 140, + width: 200, render: (value: any, record: any) => { return (
@@ -257,6 +291,19 @@ const AutoPage = (props: any) => { <> )} {global.hasPermission(ClustersPermissionMap.TOPIC_DEL) ? : <>} + {global.hasPermission(ClustersPermissionMap.TOPIC_DEL) ? ( // TODO:替换为清除数据的权限 + deleteTopicData(record)} + okText="是" + cancelText="否" + > + + + ) : ( + <> + )}
); }, From 6385889902174459934ef4e1a92a0eddde2d513c Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 10 Sep 2023 16:14:48 +0800 Subject: [PATCH 12/48] =?UTF-8?q?'[Feature]=E6=96=B0=E5=A2=9E=E5=88=A0?= =?UTF-8?q?=E9=99=A4Group=E6=88=96GroupOffset=E5=8A=9F=E8=83=BD(didi#1040)?= =?UTF-8?q?'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layout-clusters-fe/src/api/index.ts | 2 +- .../src/pages/ConsumerGroup/Delete.tsx | 104 ++++++++++++++++++ .../src/pages/ConsumerGroup/Detail.tsx | 21 +++- .../src/pages/ConsumerGroup/config.tsx | 29 ++++- .../src/pages/ConsumerGroup/index.tsx | 7 +- 5 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Delete.tsx 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 7dadd9ec8..6967e243e 100755 --- a/km-console/packages/layout-clusters-fe/src/api/index.ts +++ b/km-console/packages/layout-clusters-fe/src/api/index.ts @@ -95,7 +95,7 @@ const api = { getApi(`/clusters/${clusterPhyId}/groups/${groupName}/partitions`), resetGroupOffset: () => getApi('/group-offsets'), getGroupOverview: (clusterPhyId: number) => getApi(`/clusters/${clusterPhyId}/groups-overview`), - + deleteGroupOffset: () => getApi('/group-offsets'), // topics列表 getTopicsList: (clusterPhyId: number) => getApi(`/clusters/${clusterPhyId}/topics-overview`), getReassignmentList: () => getApi(`/reassignment/topics-overview`), diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Delete.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Delete.tsx new file mode 100644 index 000000000..ae7f959aa --- /dev/null +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Delete.tsx @@ -0,0 +1,104 @@ +import React, { useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { Button, Form, Input, Modal, Utils } from 'knowdesign'; +import notification from '@src/components/Notification'; +import Api from '@src/api/index'; + +// eslint-disable-next-line react/display-name +export default (props: { record: any; onConfirm?: () => void }) => { + const { record, onConfirm } = props; + const routeParams = useParams<{ + clusterId: string; + }>(); + const [form] = Form.useForm(); + const [delDialogVisible, setDelDialogVisble] = useState(false); + const handleDelOk = () => { + form.validateFields().then((e) => { + const formVal = form.getFieldsValue(); + formVal.clusterPhyId = Number(routeParams.clusterId); + formVal.deleteType = 0; + Utils.delete(Api.deleteGroupOffset(), { data: formVal }).then((res: any) => { + if (res === null) { + notification.success({ + message: '删除消费组成功', + }); + setDelDialogVisble(false); + onConfirm && onConfirm(); + } else { + notification.error({ + message: '删除消费组失败', + }); + } + }); + }); + }; + return ( + <> + + { + setDelDialogVisble(false); + }} + okText="删除" + okButtonProps={{ + danger: true, + size: 'small', + style: { + paddingLeft: '16px', + paddingRight: '16px', + }, + }} + cancelButtonProps={{ + size: 'small', + style: { + paddingLeft: '16px', + paddingRight: '16px', + }, + }} + > + {/*
+ + 会删除Topic的全部消息数据和ACL权限!请再次输入Topic名称进行确认! +
*/} +
+ {record.name} + ({ + validator(_, value) { + if (!value) { + return Promise.reject(new Error('请输入Group名称')); + } else if (value !== record.name) { + return Promise.reject(new Error('请输入正确的Group名称')); + } + return Promise.resolve(); + }, + }), + ]} + > + + +
+
+ + ); +}; diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx index f01bee14d..44d613740 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/Detail.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { useParams, useHistory } from 'react-router-dom'; -import { Button, Space, Divider, Drawer, ProTable, Utils } from 'knowdesign'; +import { Button, Space, Divider, Drawer, ProTable, Utils, notification } from 'knowdesign'; import { IconFont } from '@knowdesign/icons'; import API from '@src/api/index'; import { defaultPagination, hashDataParse } from '@src/constants/common'; @@ -112,6 +112,23 @@ const GroupDetail = (props: any) => { groupName: record?.groupName, }); }; + // 删除消费组Topic + const deleteOffset = (record: any) => { + const params = { + clusterPhyId: +urlParams?.clusterId, + deleteType: 1, // 0:group纬度,1:Topic纬度,2:Partition纬度 + groupName: record.groupName, + topicName: record.topicName, + }; + Utils.delete(API.deleteGroupOffset(), { data: params }).then((data: any) => { + if (data === null) { + notification.success({ + message: '删除Topic成功!', + }); + genData({ pageNo: 1, pageSize: pagination.pageSize, groupName: hashData.groupName }); + } + }); + }; const onTableChange = (pagination: any, filters: any, sorter: any) => { genData({ pageNo: pagination.current, pageSize: pagination.pageSize, filters, sorter, groupName: hashData.groupName }); @@ -199,7 +216,7 @@ const GroupDetail = (props: any) => { showHeader: false, rowKey: 'key', loading: loading, - columns: getGtoupTopicColumns({ resetOffset }), + columns: getGtoupTopicColumns({ resetOffset, deleteOffset }), dataSource: topicData, paginationProps: { ...pagination }, // noPagination: true, diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/config.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/config.tsx index 8edd92802..40b4a7f4c 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/config.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/config.tsx @@ -1,8 +1,9 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import React from 'react'; -import { AppContainer } from 'knowdesign'; +import { AppContainer, Button, Popconfirm } from 'knowdesign'; import TagsWithHide from '@src/components/TagsWithHide'; import { ClustersPermissionMap } from '../CommonConfig'; +import Delete from './Delete'; export const runningStatusEnum: any = { 1: 'Doing', @@ -62,6 +63,21 @@ export const getGroupColumns = (arg?: any) => { width: 200, render: (t: number) => (t ? t.toLocaleString() : '-'), }, + { + title: '操作', + dataIndex: 'options', + key: 'options', + width: 200, + filterTitle: true, + fixed: 'right', + render: (_t: any, r: any) => { + return ( +
+ +
+ ); + }, + }, ]; return columns; }; @@ -103,11 +119,20 @@ export const getGtoupTopicColumns = (arg?: any) => { title: '操作', dataIndex: 'desc', key: 'desc', - width: 150, + width: 200, render: (value: any, record: any) => { return (
arg.resetOffset(record)}>重置Offset + arg.deleteOffset(record)} + okText="是" + cancelText="否" + > + +
); }, diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/index.tsx index 8e0bb6fba..b54a5878a 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/index.tsx @@ -58,6 +58,11 @@ const BrokerList: React.FC = (props: any) => { genData({ pageNo: pagination.current, pageSize: pagination.pageSize, filters, sorter }); }; + // 删除Group + const deleteTesk = () => { + genData({ pageNo: 1, pageSize: pagination.pageSize }); + }; + useEffect(() => { genData({ pageNo: 1, @@ -115,7 +120,7 @@ const BrokerList: React.FC = (props: any) => { showHeader: false, rowKey: 'group_list', loading: loading, - columns: getGroupColumns(), + columns: getGroupColumns(deleteTesk), dataSource: data, paginationProps: { ...pagination }, attrs: { From 18e00f043ea35d60c9682e2ff4acf698971fc4f5 Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 10 Sep 2023 16:46:14 +0800 Subject: [PATCH 13/48] =?UTF-8?q?[Bugfix]Connect-JMX=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E7=BB=B4=E6=8A=A4=E4=BF=A1=E6=81=AF=E9=94=99=E8=AF=AF(#1044)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/MutliClusterPage/AccessCluster.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx b/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx index 28992f47d..c541da9c9 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx @@ -522,7 +522,7 @@ const ConnectorForm = (props: { const params = { ...values, id: initFieldsValue?.id, - jmxProperties: values.jmxProperties ? `{ "jmxProperties": "${values.jmxProperties}" }` : undefined, + jmxProperties: values.jmxProperties ? `{ "jmxPort": "${values.jmxProperties}" }` : undefined, }; Utils.put(api.batchConnectClusters, [params]) .then((res) => { From 1a42472fd830307f6fd39ee068cb7d5528b06200 Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 10 Sep 2023 17:17:20 +0800 Subject: [PATCH 14/48] =?UTF-8?q?[Optimize]Connect=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=9C=AA=E6=8E=A5=E5=85=A5=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E6=89=80=E6=9C=89=E7=94=A8=E6=88=B7=E9=83=BD=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E9=87=8D=E5=90=AF=E3=80=81=E7=BC=96=E8=BE=91=E3=80=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4(#1050)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/CommonConfig.tsx | 6 ++ .../src/pages/Connect/config.tsx | 61 ++++++++++++------- .../src/pages/Connect/index.tsx | 33 +++++----- 3 files changed, 64 insertions(+), 36 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx index 4d01da979..712e98fc8 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx @@ -39,6 +39,12 @@ export enum ClustersPermissionMap { MM2_DELETE = 'MM2-删除', MM2_RESTART = 'MM2-重启', MM2_STOP_RESUME = 'MM2-暂停&恢复', + // Connector + CONNECTOR_ADD = 'Connector-新增', + CONNECTOR_CHANGE_CONFIG = 'Connector-编辑', + CONNECTOR_DELETE = 'Connector-删除', + CONNECTOR_RESTART = 'Connector-重启', + CONNECTOR_STOP_RESUME = 'Connector-暂停&恢复', } export interface PermissionNode { diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx index 67691d746..84c2b5190 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx @@ -1,8 +1,9 @@ import SmallChart from '@src/components/SmallChart'; import TagsWithHide from '@src/components/TagsWithHide'; -import { Button, Tag, Tooltip, Utils, Popconfirm } from 'knowdesign'; +import { Button, Tag, Tooltip, Utils, Popconfirm, AppContainer } from 'knowdesign'; import React from 'react'; import Delete from './Delete'; +import { ClustersPermissionMap } from '../CommonConfig'; export const defaultPagination = { current: 1, pageSize: 10, @@ -93,7 +94,8 @@ const renderLine = (record: any, metricName: string) => { }; export const getConnectorsColumns = (arg?: any) => { - const columns = [ + const [global] = AppContainer.useGlobalValue(); + const columns: any = [ { title: 'Connector Name', dataIndex: 'connectorName', @@ -213,7 +215,10 @@ export const getConnectorsColumns = (arg?: any) => { return t && t.length > 0 ? `共有${num}个`} /> : '-'; }, }, - { + ]; + + if (global.hasPermission) { + columns.push({ title: '操作', dataIndex: 'options', key: 'options', @@ -224,20 +229,24 @@ export const getConnectorsColumns = (arg?: any) => { render: (_t: any, r: any) => { return (
- arg?.optionConnect(r, 'restart')} - // onCancel={cancel} - okText="是" - cancelText="否" - overlayClassName="connect-popconfirm" - > - - + {global.hasPermission(ClustersPermissionMap.CONNECTOR_RESTART) ? ( + arg?.optionConnect(r, 'restart')} + // onCancel={cancel} + okText="是" + cancelText="否" + overlayClassName="connect-popconfirm" + > + + + ) : ( + <> + )} - {(r.state === 'RUNNING' || r.state === 'PAUSED') && ( + {global.hasPermission(ClustersPermissionMap.CONNECTOR_STOP_RESUME) && (r.state === 'RUNNING' || r.state === 'PAUSED') && ( arg?.optionConnect(r, r.state === 'RUNNING' ? 'stop' : 'resume')} @@ -252,16 +261,24 @@ export const getConnectorsColumns = (arg?: any) => { )} + {global.hasPermission(ClustersPermissionMap.CONNECTOR_CHANGE_CONFIG) ? ( + + ) : ( + <> + )} - - + {global.hasPermission(ClustersPermissionMap.CONNECTOR_DELETE) ? ( + + ) : ( + <> + )}
); }, - }, - ]; + }); + } return columns; }; diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/index.tsx index 4c8dbb886..e07a047ae 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/index.tsx @@ -12,6 +12,7 @@ import notification from '@src/components/Notification'; import './index.less'; import AddConnectorUseJSON from './AddConnectorUseJSON'; import HasConnector from './HasConnector'; +import { ClustersPermissionMap } from '../CommonConfig'; const { request } = Utils; const rateMap: any = { @@ -174,21 +175,25 @@ const Connectors: React.FC = () => { maxLength: 128, }} /> - - - - - - + + + + + ) : ( + <> + )}
Date: Sun, 10 Sep 2023 22:31:20 +0800 Subject: [PATCH 15/48] =?UTF-8?q?[Bugfix]=E5=8E=BB=E9=99=A4=E7=BC=96?= =?UTF-8?q?=E8=BE=91connect=E5=A4=B1=E8=B4=A5=E5=A4=9A=E4=BD=99=E7=9A=84?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=BF=A1=E6=81=AF(#1044)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/MutliClusterPage/AccessCluster.tsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx b/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx index c541da9c9..50ab0a372 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/MutliClusterPage/AccessCluster.tsx @@ -524,19 +524,13 @@ const ConnectorForm = (props: { id: initFieldsValue?.id, jmxProperties: values.jmxProperties ? `{ "jmxPort": "${values.jmxProperties}" }` : undefined, }; - Utils.put(api.batchConnectClusters, [params]) - .then((res) => { - // setSelectedTabKey(undefined); - getConnectClustersList(); - notification.success({ - message: '修改Connect集群成功', - }); - }) - .catch((error) => { - notification.success({ - message: '修改Connect集群失败', - }); + Utils.put(api.batchConnectClusters, [params]).then((res) => { + // setSelectedTabKey(undefined); + getConnectClustersList(); + notification.success({ + message: '修改Connect集群成功', }); + }); }; const onCancel = () => { From 128b180c83bf719340d92bbe57c45114668c8458 Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 10 Sep 2023 22:45:59 +0800 Subject: [PATCH 16/48] =?UTF-8?q?[Bugfix]=E5=8E=BB=E9=99=A4=E5=88=A0?= =?UTF-8?q?=E9=99=A4Truncate=E6=97=B6=E7=9A=84=E5=A4=9A=E4=BD=99=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../packages/layout-clusters-fe/src/pages/TopicList/index.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx index 9521e5c46..0a00fa049 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicList/index.tsx @@ -112,10 +112,6 @@ const AutoPage = (props: any) => { message: '清除数据成功', }); getTopicsList(); - } else { - notification.error({ - message: '清除数据失败', - }); } }); }; From 3b72f732be68edb4750ffa33b675ebf8450198eb Mon Sep 17 00:00:00 2001 From: EricZeng Date: Wed, 27 Sep 2023 14:05:45 +0800 Subject: [PATCH 17/48] =?UTF-8?q?[Optimize]=E4=BC=98=E5=8C=96=E9=9B=86?= =?UTF-8?q?=E7=BE=A4Brokers=E4=B8=AD,=20Controller=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E5=BB=B6=E8=BF=9F=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20(#1162)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化方式: 从DB获取调整为从Kafka中实时获取。 --- .../km/biz/cluster/ClusterBrokersManager.java | 3 ++- .../impl/ClusterBrokersManagerImpl.java | 26 ++++++++++++++----- .../v3/cluster/ClusterBrokersController.java | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) 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..38a2ea4d5 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 @@ -2,6 +2,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.dto.cluster.ClusterBrokersOverviewDTO; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.PaginationResult; +import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersOverviewVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersStateVO; @@ -22,5 +23,5 @@ public interface ClusterBrokersManager { * @param clusterPhyId 物理集群 id * @return 返回根据物理集群id获取到的集群对应broker状态信息 */ - ClusterBrokersStateVO getClusterPhyBrokersState(Long clusterPhyId); + Result getClusterPhyBrokersState(Long clusterPhyId); } 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..994773705 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 @@ -12,11 +12,13 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.BrokerMetrics; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.PaginationResult; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; +import com.xiaojukeji.know.streaming.km.common.bean.entity.result.ResultStatus; import com.xiaojukeji.know.streaming.km.common.bean.entity.topic.Topic; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersOverviewVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersStateVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.kafkacontroller.KafkaControllerVO; import com.xiaojukeji.know.streaming.km.common.constant.KafkaConstant; +import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; import com.xiaojukeji.know.streaming.km.common.enums.SortTypeEnum; import com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterRunStateEnum; import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; @@ -26,6 +28,7 @@ import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerConfigService; import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerMetricService; import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerService; +import com.xiaojukeji.know.streaming.km.core.service.cluster.ClusterPhyService; import com.xiaojukeji.know.streaming.km.core.service.kafkacontroller.KafkaControllerService; import com.xiaojukeji.know.streaming.km.core.service.topic.TopicService; import com.xiaojukeji.know.streaming.km.persistence.cache.LoadedClusterPhyCache; @@ -60,6 +63,9 @@ public class ClusterBrokersManagerImpl implements ClusterBrokersManager { @Autowired private KafkaJMXClient kafkaJMXClient; + @Autowired + private ClusterPhyService clusterPhyService; + @Override public PaginationResult getClusterPhyBrokersOverview(Long clusterPhyId, ClusterBrokersOverviewDTO dto) { // 获取集群Broker列表 @@ -108,7 +114,12 @@ public PaginationResult getClusterPhyBrokersOverview(L } @Override - public ClusterBrokersStateVO getClusterPhyBrokersState(Long clusterPhyId) { + public Result getClusterPhyBrokersState(Long clusterPhyId) { + ClusterPhy clusterPhy = clusterPhyService.getClusterByCluster(clusterPhyId); + if (clusterPhy == null) { + return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getClusterPhyNotExist(clusterPhyId)); + } + ClusterBrokersStateVO clusterBrokersStateVO = new ClusterBrokersStateVO(); // 获取集群Broker列表 @@ -126,24 +137,25 @@ public ClusterBrokersStateVO getClusterPhyBrokersState(Long clusterPhyId) { ); // 获取controller信息 - KafkaController kafkaController = kafkaControllerService.getKafkaControllerFromDB(clusterPhyId); + Result controllerResult = kafkaControllerService.getControllerFromKafka(clusterPhy); // 设置kafka-controller信息 clusterBrokersStateVO.setKafkaControllerAlive(false); - if(null != kafkaController) { + if(null != controllerResult.getData()) { clusterBrokersStateVO.setKafkaController( this.convert2KafkaControllerVO( - kafkaController, - brokerService.getBroker(clusterPhyId, kafkaController.getBrokerId()) + controllerResult.getData(), + brokerService.getBroker(clusterPhyId, controllerResult.getData().getBrokerId()) ) ); clusterBrokersStateVO.setKafkaControllerAlive(true); } - clusterBrokersStateVO.setConfigSimilar(brokerConfigService.countBrokerConfigDiffsFromDB(clusterPhyId, KafkaConstant.CONFIG_SIMILAR_IGNORED_CONFIG_KEY_LIST) <= 0 + clusterBrokersStateVO.setConfigSimilar( + brokerConfigService.countBrokerConfigDiffsFromDB(clusterPhyId, KafkaConstant.CONFIG_SIMILAR_IGNORED_CONFIG_KEY_LIST) <= 0 ); - return clusterBrokersStateVO; + return Result.buildSuc(clusterBrokersStateVO); } /**************************************************** private method ****************************************************/ 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..7d8d6ee0e 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 @@ -52,7 +52,7 @@ public Result> getClusterPhyBrokersMetadata(@PathVariable @GetMapping(value = "clusters/{clusterPhyId}/brokers-state") @ResponseBody public Result getClusterPhyBrokersState(@PathVariable Long clusterPhyId) { - return Result.buildSuc(clusterBrokersManager.getClusterPhyBrokersState(clusterPhyId)); + return clusterBrokersManager.getClusterPhyBrokersState(clusterPhyId); } @ApiOperation(value = "集群brokers信息列表") From 3f817991aa824842ddfdd838334399af2ba72e66 Mon Sep 17 00:00:00 2001 From: erge <64293299+Wyb7290@users.noreply.github.com> Date: Sun, 15 Oct 2023 11:15:39 +0800 Subject: [PATCH 18/48] =?UTF-8?q?[Bugfix]=E4=BC=98=E5=8C=96=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E5=AD=90=E5=BA=94=E7=94=A8=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=AD=A3=E5=B8=B8=E5=90=AF=E5=8A=A8=20(#1167)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../packages/config-manager-fe/config/webpack.common.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/km-console/packages/config-manager-fe/config/webpack.common.js b/km-console/packages/config-manager-fe/config/webpack.common.js index cef88e615..7521137bc 100644 --- a/km-console/packages/config-manager-fe/config/webpack.common.js +++ b/km-console/packages/config-manager-fe/config/webpack.common.js @@ -16,6 +16,13 @@ const babelOptions = { cacheDirectory: true, babelrc: false, presets: [require.resolve('@babel/preset-env'), require.resolve('@babel/preset-typescript'), require.resolve('@babel/preset-react')], + overrides: [ + // TODO:编译时需要做的事情更多,应该只针对目标第三方库 + { + include: './node_modules', + sourceType: 'unambiguous' + } + ], plugins: [ [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }], [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], From 1adfa639ac43704e113b266d37fa8e50709fead6 Mon Sep 17 00:00:00 2001 From: erge <64293299+Wyb7290@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:39:21 +0800 Subject: [PATCH 19/48] =?UTF-8?q?[Bugfix]Connect-JSON=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E7=9A=84JSON=E6=A0=BC=E5=BC=8F=E5=92=8C=E5=AE=98?= =?UTF-8?q?=E6=96=B9API=E7=9A=84=E6=A0=BC=E5=BC=8F=E4=B8=8D=E4=B8=80?= =?UTF-8?q?=E8=87=B4(#1048)=20(#1153)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 请不要在没有先创建Issue的情况下创建Pull Request。 ## 变更的目的是什么 XXXXX ## 简短的更新日志 XX ## 验证这一变化 XXXX 请遵循此清单,以帮助我们快速轻松地整合您的贡献: * [ ] 一个 PR(Pull Request的简写)只解决一个问题,禁止一个 PR 解决多个问题; * [ ] 确保 PR 有对应的 Issue(通常在您开始处理之前创建),除非是书写错误之类的琐碎更改不需要 Issue ; * [ ] 格式化 PR 及 Commit-Log 的标题及内容,例如 #861 。PS:Commit-Log 需要在 Git Commit 代码时进行填写,在 GitHub 上修改不了; * [ ] 编写足够详细的 PR 描述,以了解 PR 的作用、方式和原因; * [ ] 编写必要的单元测试来验证您的逻辑更正。如果提交了新功能或重大更改,请记住在 test 模块中添加 integration-test; * [ ] 确保编译通过,集成测试通过; --- .../src/pages/Connect/AddConnector.tsx | 10 +++---- .../src/pages/Connect/AddConnectorUseJSON.tsx | 30 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx index ef6a55bdf..5ecdcce10 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx @@ -949,7 +949,7 @@ export default forwardRef( success?: { connectClusterId: number; connectorName: string; - configs: { + config: { [key: string]: any; }; }; @@ -991,7 +991,7 @@ export default forwardRef( success: { connectClusterId: res[0].connectClusterId, connectorName: result['name'], - configs: result, + config: result, }, }); }, @@ -1015,7 +1015,7 @@ export default forwardRef( curClusterName = cluster.label; } }); - (jsonRef as any)?.onOpen(operateInfo.type, curClusterName, info.success.configs); + (jsonRef as any)?.onOpen(operateInfo.type, curClusterName, info.success.config); onClose(); } }); @@ -1028,9 +1028,9 @@ export default forwardRef( setCurrentStep(info.error); } else { setSubmitLoading(true); - Object.entries(info.success.configs).forEach(([key, val]) => { + Object.entries(info.success.config).forEach(([key, val]) => { if (val === null) { - delete info.success.configs[key]; + delete info.success.config[key]; } }); Utils.put(api.validateConnectorConfig, info.success).then( diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx index b93513460..e06ede24e 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx @@ -10,7 +10,7 @@ const PLACEHOLDER = `配置格式如下 { "connectClusterName": "", // Connect Cluster 名称 - "configs": { // 具体配置项 + "config": { // 具体配置项 "name": "", "connector.class": "", "tasks.max": 1, @@ -47,7 +47,7 @@ export default forwardRef((props: any, ref) => { configs: JSON.stringify( { connectClusterName, - configs: defaultConfigs, + config: defaultConfigs, }, null, 2 @@ -63,13 +63,13 @@ export default forwardRef((props: any, ref) => { form.validateFields().then( (data) => { const postData = JSON.parse(data.configs); - postData.connectorName = postData.configs.name; + postData.connectorName = postData.config.name; postData.connectClusterId = connectClusters.find((cluster) => cluster.label === postData.connectClusterName).value; delete postData.connectClusterName; - Object.entries(postData.configs).forEach(([key, val]) => { + Object.entries(postData.config).forEach(([key, val]) => { if (val === null) { - delete postData.configs[key]; + delete postData.config[key]; } }); Utils.put(api.validateConnectorConfig, postData).then( @@ -198,20 +198,20 @@ export default forwardRef((props: any, ref) => { } } - if (!v.configs || typeof v.configs !== 'object') { - return Promise.reject('内容缺少 configs 字段或字段格式错误'); + if (!v.config || typeof v.config !== 'object') { + return Promise.reject('内容缺少 config 字段或字段格式错误'); } else { // 校验 connectorName 字段 - if (!v.configs.name) { - return Promise.reject('configs 字段下缺少 name 项'); + if (!v.config.name) { + return Promise.reject('config 字段下缺少 name 项'); } else { - if (type === 'edit' && v.configs.name !== defaultConfigs.name) { + if (type === 'edit' && v.config.name !== defaultConfigs.name) { return Promise.reject('编辑模式下不允许修改 name 字段'); } } - if (!v.configs['connector.class']) { - return Promise.reject('configs 字段下缺少 connector.class 项'); - } else if (type === 'edit' && v.configs['connector.class'] !== defaultConfigs['connector.class']) { + if (!v.config['connector.class']) { + return Promise.reject('config 字段下缺少 connector.class 项'); + } else if (type === 'edit' && v.config['connector.class'] !== defaultConfigs['connector.class']) { return Promise.reject('编辑模式下不允许修改 connector.class 字段'); } } @@ -219,13 +219,13 @@ export default forwardRef((props: any, ref) => { if (type === 'create') { // 异步校验 connector 名称是否重复 以及 className 是否存在 return Promise.all([ - Utils.request(api.isConnectorExist(connectClusterId, v.configs.name)), + Utils.request(api.isConnectorExist(connectClusterId, v.config.name)), Utils.request(api.getConnectorPlugins(connectClusterId)), ]).then( ([data, plugins]: [any, ConnectorPlugin[]]) => { return data?.exist ? Promise.reject('name 与已有 Connector 重复') - : plugins.every((plugin) => plugin.className !== v.configs['connector.class']) + : plugins.every((plugin) => plugin.className !== v.config['connector.class']) ? Promise.reject('该 connectCluster 下不存在 connector.class 项配置的插件') : Promise.resolve(); }, From 07bd00d60c486d582c8d30a8aa69ae610c4960a4 Mon Sep 17 00:00:00 2001 From: erge <64293299+Wyb7290@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:40:07 +0800 Subject: [PATCH 20/48] =?UTF-8?q?[Optimize]security=E4=B8=8B=E7=9A=84users?= =?UTF-8?q?=E3=80=81acls=E6=8E=A5=E5=85=A5=E8=BF=9B=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=AE=A1=E7=90=86(#1089)=20(#1154)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 请不要在没有先创建Issue的情况下创建Pull Request。 ## 变更的目的是什么 XXXXX ## 简短的更新日志 XX ## 验证这一变化 XXXX 请遵循此清单,以帮助我们快速轻松地整合您的贡献: * [ ] 一个 PR(Pull Request的简写)只解决一个问题,禁止一个 PR 解决多个问题; * [ ] 确保 PR 有对应的 Issue(通常在您开始处理之前创建),除非是书写错误之类的琐碎更改不需要 Issue ; * [ ] 格式化 PR 及 Commit-Log 的标题及内容,例如 #861 。PS:Commit-Log 需要在 Git Commit 代码时进行填写,在 GitHub 上修改不了; * [ ] 编写足够详细的 PR 描述,以了解 PR 的作用、方式和原因; * [ ] 编写必要的单元测试来验证您的逻辑更正。如果提交了新功能或重大更改,请记住在 test 模块中添加 integration-test; * [ ] 确保编译通过,集成测试通过; --- .../src/pages/CommonConfig.tsx | 6 ++ .../src/pages/SecurityACLs/index.tsx | 33 ++++++---- .../src/pages/SecurityUsers/index.tsx | 61 +++++++++++-------- 3 files changed, 63 insertions(+), 37 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx index 712e98fc8..d168b8048 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx @@ -45,6 +45,12 @@ export enum ClustersPermissionMap { CONNECTOR_DELETE = 'Connector-删除', CONNECTOR_RESTART = 'Connector-重启', CONNECTOR_STOP_RESUME = 'Connector-暂停&恢复', + // Security + SECURITY_ACL_ADD = 'Security-ACL新增', + SECURITY_ACL_DELETE = 'Security-ACL删除', + SECURITY_USER_ADD = 'Security-User新增', + SECURITY_USER_DELETE = 'Security-User删除', + SECURITY_USER_EDIT_PASSWORD = 'Security-User修改密码', } export interface PermissionNode { diff --git a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx index 9919afdda..46befe501 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx @@ -14,6 +14,7 @@ import AddACLDrawer, { RESOURCE_TO_OPERATIONS_MAP, RESOURCE_MAP_KEYS, } from './EditDrawer'; +import { ClustersPermissionMap } from '../CommonConfig'; import './index.less'; const { confirm } = Modal; @@ -105,7 +106,7 @@ const SecurityACLs = (): JSX.Element => { }; const columns = () => { - const baseColumns = [ + const baseColumns: any = [ { title: 'Principal', dataIndex: 'kafkaUser', @@ -143,7 +144,9 @@ const SecurityACLs = (): JSX.Element => { title: 'Host', dataIndex: 'aclClientHost', }, - { + ]; + if (global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_ACL_DELETE)) { + baseColumns.push({ title: '操作', dataIndex: '', width: 120, @@ -156,8 +159,8 @@ const SecurityACLs = (): JSX.Element => { ); }, - }, - ]; + }); + } return baseColumns; }; @@ -238,15 +241,19 @@ const SecurityACLs = (): JSX.Element => {
-
- -
+ {global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_ACL_ADD) ? ( +
+ +
+ ) : ( + <> + )}
{ const maxPos = chars.length; let str = ''; @@ -323,7 +323,7 @@ const SecurityUsers = (): JSX.Element => { }; const columns = () => { - const baseColumns = [ + const baseColumns: any = [ { title: 'KafkaUser', dataIndex: 'name', @@ -348,30 +348,39 @@ const SecurityUsers = (): JSX.Element => { return ; }, }, - { + ]; + if (global.hasPermission) { + baseColumns.push({ title: '操作', dataIndex: '', width: 240, render(record: UsersProps) { return ( <> - - + {global.hasPermission(ClustersPermissionMap.SECURITY_USER_EDIT_PASSWORD) ? ( + + ) : ( + <> + )} + {global.hasPermission(ClustersPermissionMap.SECURITY_USER_DELETE) ? ( + + ) : ( + <> + )} ); }, - }, - ]; - + }); + } return baseColumns; }; @@ -454,13 +463,17 @@ const SecurityUsers = (): JSX.Element => { setSearchKeywordsInput(e.target.value); }} /> - + {global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_USER_ADD) ? ( + + ) : ( + <> + )} From f6becbdf2c7de633d71a665b4014f6bc9cd0f8a0 Mon Sep 17 00:00:00 2001 From: erge <64293299+Wyb7290@users.noreply.github.com> Date: Fri, 20 Oct 2023 09:28:52 +0800 Subject: [PATCH 21/48] =?UTF-8?q?[Optimize]Connect=20=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8F=98=E6=9B=B4=E4=B8=BA=E5=8F=AA=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E7=94=A8=E6=88=B7=E4=BF=AE=E6=94=B9=E7=9A=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE,=E5=B9=B6=E4=BF=AE=E5=A4=8DJSON=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E9=85=8D=E7=BD=AE=E5=B1=95=E7=A4=BA=E4=B8=8D=E5=85=A8?= =?UTF-8?q?(#1047)=20(#1158)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 请不要在没有先创建Issue的情况下创建Pull Request。 ## 变更的目的是什么 优化Content新增/编辑 ## 简短的更新日志 - [Bugfix] 自定义的高级配置项,在JSON模式下未显示这些配置(#1045) - [Optimize] 提交任务后只保存用户修改的配置,而不是将所有配置都保存起来,目前不论用户有没有修改配置都保存了所有的配置(#1047) ## 验证这一变化 XXXX 请遵循此清单,以帮助我们快速轻松地整合您的贡献: * [ ] 一个 PR(Pull Request的简写)只解决一个问题,禁止一个 PR 解决多个问题; * [ ] 确保 PR 有对应的 Issue(通常在您开始处理之前创建),除非是书写错误之类的琐碎更改不需要 Issue ; * [ ] 格式化 PR 及 Commit-Log 的标题及内容,例如 #861 。PS:Commit-Log 需要在 Git Commit 代码时进行填写,在 GitHub 上修改不了; * [ ] 编写足够详细的 PR 描述,以了解 PR 的作用、方式和原因; * [ ] 编写必要的单元测试来验证您的逻辑更正。如果提交了新功能或重大更改,请记住在 test 模块中添加 integration-test; * [ ] 确保编译通过,集成测试通过; --- .../km/biz/cluster/ClusterBrokersManager.java | 3 +- .../impl/ClusterBrokersManagerImpl.java | 26 +++----- .../config/webpack.common.js | 7 --- .../src/pages/CommonConfig.tsx | 6 -- .../src/pages/Connect/AddConnector.tsx | 23 ++++++- .../src/pages/Connect/AddConnectorUseJSON.tsx | 30 ++++----- .../src/pages/SecurityACLs/index.tsx | 33 ++++------ .../src/pages/SecurityUsers/index.tsx | 61 ++++++++----------- .../v3/cluster/ClusterBrokersController.java | 2 +- 9 files changed, 82 insertions(+), 109 deletions(-) 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 38a2ea4d5..8427c1ef0 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 @@ -2,7 +2,6 @@ import com.xiaojukeji.know.streaming.km.common.bean.dto.cluster.ClusterBrokersOverviewDTO; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.PaginationResult; -import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersOverviewVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersStateVO; @@ -23,5 +22,5 @@ public interface ClusterBrokersManager { * @param clusterPhyId 物理集群 id * @return 返回根据物理集群id获取到的集群对应broker状态信息 */ - Result getClusterPhyBrokersState(Long clusterPhyId); + ClusterBrokersStateVO getClusterPhyBrokersState(Long clusterPhyId); } 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 994773705..c77724dd8 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 @@ -12,13 +12,11 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.metrics.BrokerMetrics; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.PaginationResult; import com.xiaojukeji.know.streaming.km.common.bean.entity.result.Result; -import com.xiaojukeji.know.streaming.km.common.bean.entity.result.ResultStatus; import com.xiaojukeji.know.streaming.km.common.bean.entity.topic.Topic; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersOverviewVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.cluster.res.ClusterBrokersStateVO; import com.xiaojukeji.know.streaming.km.common.bean.vo.kafkacontroller.KafkaControllerVO; import com.xiaojukeji.know.streaming.km.common.constant.KafkaConstant; -import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; import com.xiaojukeji.know.streaming.km.common.enums.SortTypeEnum; import com.xiaojukeji.know.streaming.km.common.enums.cluster.ClusterRunStateEnum; import com.xiaojukeji.know.streaming.km.common.utils.ConvertUtil; @@ -28,7 +26,6 @@ import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerConfigService; import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerMetricService; import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerService; -import com.xiaojukeji.know.streaming.km.core.service.cluster.ClusterPhyService; import com.xiaojukeji.know.streaming.km.core.service.kafkacontroller.KafkaControllerService; import com.xiaojukeji.know.streaming.km.core.service.topic.TopicService; import com.xiaojukeji.know.streaming.km.persistence.cache.LoadedClusterPhyCache; @@ -63,9 +60,6 @@ public class ClusterBrokersManagerImpl implements ClusterBrokersManager { @Autowired private KafkaJMXClient kafkaJMXClient; - @Autowired - private ClusterPhyService clusterPhyService; - @Override public PaginationResult getClusterPhyBrokersOverview(Long clusterPhyId, ClusterBrokersOverviewDTO dto) { // 获取集群Broker列表 @@ -114,12 +108,7 @@ public PaginationResult getClusterPhyBrokersOverview(L } @Override - public Result getClusterPhyBrokersState(Long clusterPhyId) { - ClusterPhy clusterPhy = clusterPhyService.getClusterByCluster(clusterPhyId); - if (clusterPhy == null) { - return Result.buildFromRSAndMsg(ResultStatus.NOT_EXIST, MsgConstant.getClusterPhyNotExist(clusterPhyId)); - } - + public ClusterBrokersStateVO getClusterPhyBrokersState(Long clusterPhyId) { ClusterBrokersStateVO clusterBrokersStateVO = new ClusterBrokersStateVO(); // 获取集群Broker列表 @@ -137,25 +126,24 @@ public Result getClusterPhyBrokersState(Long clusterPhyId ); // 获取controller信息 - Result controllerResult = kafkaControllerService.getControllerFromKafka(clusterPhy); + KafkaController kafkaController = kafkaControllerService.getKafkaControllerFromDB(clusterPhyId); // 设置kafka-controller信息 clusterBrokersStateVO.setKafkaControllerAlive(false); - if(null != controllerResult.getData()) { + if(null != kafkaController) { clusterBrokersStateVO.setKafkaController( this.convert2KafkaControllerVO( - controllerResult.getData(), - brokerService.getBroker(clusterPhyId, controllerResult.getData().getBrokerId()) + kafkaController, + brokerService.getBroker(clusterPhyId, kafkaController.getBrokerId()) ) ); clusterBrokersStateVO.setKafkaControllerAlive(true); } - clusterBrokersStateVO.setConfigSimilar( - brokerConfigService.countBrokerConfigDiffsFromDB(clusterPhyId, KafkaConstant.CONFIG_SIMILAR_IGNORED_CONFIG_KEY_LIST) <= 0 + clusterBrokersStateVO.setConfigSimilar(brokerConfigService.countBrokerConfigDiffsFromDB(clusterPhyId, KafkaConstant.CONFIG_SIMILAR_IGNORED_CONFIG_KEY_LIST) <= 0 ); - return Result.buildSuc(clusterBrokersStateVO); + return clusterBrokersStateVO; } /**************************************************** private method ****************************************************/ diff --git a/km-console/packages/config-manager-fe/config/webpack.common.js b/km-console/packages/config-manager-fe/config/webpack.common.js index 7521137bc..cef88e615 100644 --- a/km-console/packages/config-manager-fe/config/webpack.common.js +++ b/km-console/packages/config-manager-fe/config/webpack.common.js @@ -16,13 +16,6 @@ const babelOptions = { cacheDirectory: true, babelrc: false, presets: [require.resolve('@babel/preset-env'), require.resolve('@babel/preset-typescript'), require.resolve('@babel/preset-react')], - overrides: [ - // TODO:编译时需要做的事情更多,应该只针对目标第三方库 - { - include: './node_modules', - sourceType: 'unambiguous' - } - ], plugins: [ [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }], [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], diff --git a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx index d168b8048..712e98fc8 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx @@ -45,12 +45,6 @@ export enum ClustersPermissionMap { CONNECTOR_DELETE = 'Connector-删除', CONNECTOR_RESTART = 'Connector-重启', CONNECTOR_STOP_RESUME = 'Connector-暂停&恢复', - // Security - SECURITY_ACL_ADD = 'Security-ACL新增', - SECURITY_ACL_DELETE = 'Security-ACL删除', - SECURITY_USER_ADD = 'Security-User新增', - SECURITY_USER_DELETE = 'Security-User删除', - SECURITY_USER_EDIT_PASSWORD = 'Security-User修改密码', } export interface PermissionNode { diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx index 5ecdcce10..fa9f857dd 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnector.tsx @@ -189,7 +189,14 @@ const StepFormFirst = (props: SubFormProps) => { const result: FormConnectorConfigs = { pluginConfig: {}, }; + + // 获取一份默认配置 + const defaultPluginConfig: any = {}; + pluginConfig.configs.forEach(({ definition }) => { + // 获取一份默认配置 + defaultPluginConfig[definition.name] = definition?.defaultValue; + if (!getExistFormItems(pluginType).includes(definition.name)) { const pluginConfigs = result.pluginConfig; const group = definition.group || 'Others'; @@ -205,7 +212,7 @@ const StepFormFirst = (props: SubFormProps) => { Object.keys(result).length && form.setFieldsValue({ - configs: result, + configs: { ...result, defaultPluginConfig, editConnectorConfig: result.connectorConfig }, }); }) .finally(() => props.setSubmitLoading(false)); @@ -957,6 +964,7 @@ export default forwardRef( }) => void ) => { const promises: Promise[] = []; + const compareConfig = stepsFormRef.current[0].getFieldValue('configs'); // 获取步骤一的form信息 Object.values(stepsFormRef.current).forEach((form, i) => { const promise = form .validateFields() @@ -987,11 +995,22 @@ export default forwardRef( const [k, ...v] = l.split('='); result[k] = v.join('='); }); + + const editConnectorConfig = operateInfo.type === 'edit' ? compareConfig.editConnectorConfig : {}; // 编辑状态时拿到config配置 + const newCompareConfig = { ...compareConfig.defaultPluginConfig, ...editConnectorConfig, ...result }; // 整合后的表单提交信息 + Object.keys(newCompareConfig).forEach((item) => { + if ( + newCompareConfig[item] === compareConfig.defaultPluginConfig[item] || + newCompareConfig[item]?.toString() === compareConfig.defaultPluginConfig[item]?.toString() + ) { + delete newCompareConfig[item]; // 清除默认值 + } + }); callback({ success: { connectClusterId: res[0].connectClusterId, connectorName: result['name'], - config: result, + config: newCompareConfig, }, }); }, diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx index e06ede24e..b93513460 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx @@ -10,7 +10,7 @@ const PLACEHOLDER = `配置格式如下 { "connectClusterName": "", // Connect Cluster 名称 - "config": { // 具体配置项 + "configs": { // 具体配置项 "name": "", "connector.class": "", "tasks.max": 1, @@ -47,7 +47,7 @@ export default forwardRef((props: any, ref) => { configs: JSON.stringify( { connectClusterName, - config: defaultConfigs, + configs: defaultConfigs, }, null, 2 @@ -63,13 +63,13 @@ export default forwardRef((props: any, ref) => { form.validateFields().then( (data) => { const postData = JSON.parse(data.configs); - postData.connectorName = postData.config.name; + postData.connectorName = postData.configs.name; postData.connectClusterId = connectClusters.find((cluster) => cluster.label === postData.connectClusterName).value; delete postData.connectClusterName; - Object.entries(postData.config).forEach(([key, val]) => { + Object.entries(postData.configs).forEach(([key, val]) => { if (val === null) { - delete postData.config[key]; + delete postData.configs[key]; } }); Utils.put(api.validateConnectorConfig, postData).then( @@ -198,20 +198,20 @@ export default forwardRef((props: any, ref) => { } } - if (!v.config || typeof v.config !== 'object') { - return Promise.reject('内容缺少 config 字段或字段格式错误'); + if (!v.configs || typeof v.configs !== 'object') { + return Promise.reject('内容缺少 configs 字段或字段格式错误'); } else { // 校验 connectorName 字段 - if (!v.config.name) { - return Promise.reject('config 字段下缺少 name 项'); + if (!v.configs.name) { + return Promise.reject('configs 字段下缺少 name 项'); } else { - if (type === 'edit' && v.config.name !== defaultConfigs.name) { + if (type === 'edit' && v.configs.name !== defaultConfigs.name) { return Promise.reject('编辑模式下不允许修改 name 字段'); } } - if (!v.config['connector.class']) { - return Promise.reject('config 字段下缺少 connector.class 项'); - } else if (type === 'edit' && v.config['connector.class'] !== defaultConfigs['connector.class']) { + if (!v.configs['connector.class']) { + return Promise.reject('configs 字段下缺少 connector.class 项'); + } else if (type === 'edit' && v.configs['connector.class'] !== defaultConfigs['connector.class']) { return Promise.reject('编辑模式下不允许修改 connector.class 字段'); } } @@ -219,13 +219,13 @@ export default forwardRef((props: any, ref) => { if (type === 'create') { // 异步校验 connector 名称是否重复 以及 className 是否存在 return Promise.all([ - Utils.request(api.isConnectorExist(connectClusterId, v.config.name)), + Utils.request(api.isConnectorExist(connectClusterId, v.configs.name)), Utils.request(api.getConnectorPlugins(connectClusterId)), ]).then( ([data, plugins]: [any, ConnectorPlugin[]]) => { return data?.exist ? Promise.reject('name 与已有 Connector 重复') - : plugins.every((plugin) => plugin.className !== v.config['connector.class']) + : plugins.every((plugin) => plugin.className !== v.configs['connector.class']) ? Promise.reject('该 connectCluster 下不存在 connector.class 项配置的插件') : Promise.resolve(); }, diff --git a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx index 46befe501..9919afdda 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx @@ -14,7 +14,6 @@ import AddACLDrawer, { RESOURCE_TO_OPERATIONS_MAP, RESOURCE_MAP_KEYS, } from './EditDrawer'; -import { ClustersPermissionMap } from '../CommonConfig'; import './index.less'; const { confirm } = Modal; @@ -106,7 +105,7 @@ const SecurityACLs = (): JSX.Element => { }; const columns = () => { - const baseColumns: any = [ + const baseColumns = [ { title: 'Principal', dataIndex: 'kafkaUser', @@ -144,9 +143,7 @@ const SecurityACLs = (): JSX.Element => { title: 'Host', dataIndex: 'aclClientHost', }, - ]; - if (global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_ACL_DELETE)) { - baseColumns.push({ + { title: '操作', dataIndex: '', width: 120, @@ -159,8 +156,8 @@ const SecurityACLs = (): JSX.Element => { ); }, - }); - } + }, + ]; return baseColumns; }; @@ -241,19 +238,15 @@ const SecurityACLs = (): JSX.Element => {
- {global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_ACL_ADD) ? ( -
- -
- ) : ( - <> - )} +
+ +
{ const maxPos = chars.length; let str = ''; @@ -323,7 +323,7 @@ const SecurityUsers = (): JSX.Element => { }; const columns = () => { - const baseColumns: any = [ + const baseColumns = [ { title: 'KafkaUser', dataIndex: 'name', @@ -348,39 +348,30 @@ const SecurityUsers = (): JSX.Element => { return ; }, }, - ]; - if (global.hasPermission) { - baseColumns.push({ + { title: '操作', dataIndex: '', width: 240, render(record: UsersProps) { return ( <> - {global.hasPermission(ClustersPermissionMap.SECURITY_USER_EDIT_PASSWORD) ? ( - - ) : ( - <> - )} - {global.hasPermission(ClustersPermissionMap.SECURITY_USER_DELETE) ? ( - - ) : ( - <> - )} + + ); }, - }); - } + }, + ]; + return baseColumns; }; @@ -463,17 +454,13 @@ const SecurityUsers = (): JSX.Element => { setSearchKeywordsInput(e.target.value); }} /> - {global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_USER_ADD) ? ( - - ) : ( - <> - )} + 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 7d8d6ee0e..db9c933a4 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 @@ -52,7 +52,7 @@ public Result> getClusterPhyBrokersMetadata(@PathVariable @GetMapping(value = "clusters/{clusterPhyId}/brokers-state") @ResponseBody public Result getClusterPhyBrokersState(@PathVariable Long clusterPhyId) { - return clusterBrokersManager.getClusterPhyBrokersState(clusterPhyId); + return Result.buildSuc(clusterBrokersManager.getClusterPhyBrokersState(clusterPhyId)); } @ApiOperation(value = "集群brokers信息列表") From 59e8a416b56a1978980fa67f7ec1f93064675b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E5=96=9D=E8=8D=AF=E7=9A=84=E5=A4=A7=E9=83=8E?= <43955116+HZSUZJ@users.noreply.github.com> Date: Fri, 20 Oct 2023 09:32:31 +0800 Subject: [PATCH 22/48] =?UTF-8?q?[Bugfix]=E4=BF=AE=E5=A4=8D=E6=9C=AA?= =?UTF-8?q?=E5=8B=BE=E9=80=89=E7=B3=BB=E7=BB=9F=E7=AE=A1=E7=90=86=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E6=9D=83=E9=99=90=EF=BC=8C=E4=BD=86=E6=98=AF=E4=BE=9D?= =?UTF-8?q?=E7=84=B6=E5=8F=AF=E4=BB=A5=E6=9F=A5=E7=9C=8B=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=9A=84=E9=97=AE=E9=A2=98=20(#1105)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 请不要在没有先创建Issue的情况下创建Pull Request。 ## 变更的目的是什么 修复未勾选系统管理查看权限,但是依然可以查看系统管理的问题 ## 简短的更新日志 修复未勾选系统管理查看权限,但是依然可以查看系统管理的问题 ## 验证这一变化 ### 权限表 image ### 效果 image 请遵循此清单,以帮助我们快速轻松地整合您的贡献: * [x] 一个 PR(Pull Request的简写)只解决一个问题,禁止一个 PR 解决多个问题; * [x] 确保 PR 有对应的 Issue(通常在您开始处理之前创建),除非是书写错误之类的琐碎更改不需要 Issue ; * [x] 格式化 PR 及 Commit-Log 的标题及内容,例如 #861 。PS:Commit-Log 需要在 Git Commit 代码时进行填写,在 GitHub 上修改不了; * [x] 编写足够详细的 PR 描述,以了解 PR 的作用、方式和原因; * [x] 编写必要的单元测试来验证您的逻辑更正。如果提交了新功能或重大更改,请记住在 test 模块中添加 integration-test; * [x] 确保编译通过,集成测试通过; Co-authored-by: suzj --- .../packages/layout-clusters-fe/src/app.tsx | 35 +++++++++++-------- .../src/pages/CommonConfig.tsx | 10 ++++++ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/app.tsx b/km-console/packages/layout-clusters-fe/src/app.tsx index b945a9c08..4df691ebd 100755 --- a/km-console/packages/layout-clusters-fe/src/app.tsx +++ b/km-console/packages/layout-clusters-fe/src/app.tsx @@ -20,6 +20,7 @@ import { getLicenseInfo } from './constants/common'; import api from './api'; import ClusterContainer from './pages/index'; import ksLogo from './assets/ks-logo.png'; +import {ClustersPermissionMap} from "./pages/CommonConfig"; interface ILocaleMap { [index: string]: any; @@ -116,6 +117,8 @@ const AppContent = (props: { setlanguage: (language: string) => void }) => { const userInfo = localStorage.getItem('userInfo'); const [curActiveAppName, setCurActiveAppName] = useState(''); const [versionInfo, setVersionInfo] = useState(); + const [global] = AppContainer.useGlobalValue(); + const quickEntries=[]; useEffect(() => { if (pathname.startsWith('/config')) { @@ -132,6 +135,23 @@ const AppContent = (props: { setlanguage: (language: string) => void }) => { }); }, []); + if (global.hasPermission && global.hasPermission(ClustersPermissionMap.CLUSTERS_MANAGE_VIEW)){ + quickEntries.push({ + icon: , + txt: '多集群管理', + ident: '', + active: curActiveAppName === 'cluster', + }); + } + if (global.hasPermission && global.hasPermission(ClustersPermissionMap.SYS_MANAGE_VIEW)){ + quickEntries.push({ + icon: , + txt: '系统管理', + ident: 'config', + active: curActiveAppName === 'config', + }); + } + return ( void }) => { ), username: userInfo ? JSON.parse(userInfo)?.userName : '', icon: , - quickEntries: [ - { - icon: , - txt: '多集群管理', - ident: '', - active: curActiveAppName === 'cluster', - }, - { - icon: , - txt: '系统管理', - ident: 'config', - active: curActiveAppName === 'config', - }, - ], + quickEntries: quickEntries, isFixed: false, userDropMenuItems: [ diff --git a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx index 712e98fc8..722d04e67 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx @@ -7,6 +7,9 @@ import { goLogin } from '@src/constants/axiosConfig'; export enum ClustersPermissionMap { CLUSTERS_MANAGE = '多集群管理', CLUSTERS_MANAGE_VIEW = '多集群管理查看', + //仅用作隐藏掉系统管理菜单 + SYS_MANAGE = '系统管理', + SYS_MANAGE_VIEW = '系统管理查看', // Cluster CLUSTER_ADD = '接入集群', CLUSTER_DEL = '删除集群', @@ -94,6 +97,13 @@ const CommonConfig = () => { clustersPermissions && clustersPermissions.childList.forEach((node: PermissionNode) => node.has && userPermissions.push(node.permissionName)); + // 获取用户在系统管理拥有的权限 + const configPermissions = userPermissionTree.find( + (sys: PermissionNode) => sys.permissionName === ClustersPermissionMap.SYS_MANAGE + ); + configPermissions && + configPermissions.childList.forEach((node: PermissionNode) => node.has && userPermissions.push(node.permissionName)); + const hasPermission = (permissionName: ClustersPermissionMap) => permissionName && userPermissions.includes(permissionName); setGlobal((curState: any) => ({ ...curState, permissions: allPermissions, userPermissions, hasPermission, userInfo })); From 95158813b974e6ee0120a12e29a12d51f8c61ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E5=96=9D=E8=8D=AF=E7=9A=84=E5=A4=A7=E9=83=8E?= <43955116+HZSUZJ@users.noreply.github.com> Date: Fri, 20 Oct 2023 09:34:29 +0800 Subject: [PATCH 23/48] =?UTF-8?q?[Bugfix]=E4=BF=AE=E5=A4=8D=E6=B6=88?= =?UTF-8?q?=E8=B4=B9=E7=BB=84Offset=E9=87=8D=E7=BD=AE=E5=90=8E=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E9=87=8D=E7=BD=AE=E6=88=90=E5=8A=9F=EF=BC=8C?= =?UTF-8?q?=E4=BD=86=E6=98=AF=E5=89=8D=E7=AB=AF=E4=B8=8D=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8COffset=E6=97=A0=E5=8F=98=E5=8C=96?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=20(#1090)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 请不要在没有先创建Issue的情况下创建Pull Request。 ## 变更的目的是什么 修复消费组Offset重置后,提示重置成功,但是前端不刷新数据,Offset无变化的问题 ## 简短的更新日志 使用pubsub-js解决问题 ## 验证这一变化 ### 重置前: ![7c90f21063995e7a155d30a24f70c82](https://github.com/didi/KnowStreaming/assets/43955116/db10a87d-2353-48f6-bd29-71b6eb47dab9) ### 重置指定分区 ![039cf8a01ced8783ea957ab72187d83](https://github.com/didi/KnowStreaming/assets/43955116/f8cd4ac0-d093-4df2-aab3-915571bdd8de) ![84580ab27f725b68456793a47e0ad72](https://github.com/didi/KnowStreaming/assets/43955116/5ce85211-95a0-4809-accd-d57b141b4132) ### 重置最新offset ![image](https://github.com/didi/KnowStreaming/assets/43955116/227b7939-40ac-4c6c-8e92-03fc16413dce) ### 重置最旧offset ![image](https://github.com/didi/KnowStreaming/assets/43955116/56d08648-ac58-43c9-86cd-f88a2a8ae8dd) 请遵循此清单,以帮助我们快速轻松地整合您的贡献: * [x] 一个 PR(Pull Request的简写)只解决一个问题,禁止一个 PR 解决多个问题; * [x] 确保 PR 有对应的 Issue(通常在您开始处理之前创建),除非是书写错误之类的琐碎更改不需要 Issue ; * [x] 格式化 PR 及 Commit-Log 的标题及内容,例如 #861 。PS:Commit-Log 需要在 Git Commit 代码时进行填写,在 GitHub 上修改不了; * [x] 编写足够详细的 PR 描述,以了解 PR 的作用、方式和原因; * [x] 编写必要的单元测试来验证您的逻辑更正。如果提交了新功能或重大更改,请记住在 test 模块中添加 integration-test; * [x] 确保编译通过,集成测试通过; --- km-console/packages/layout-clusters-fe/package.json | 1 + .../src/pages/ConsumerGroup/ExpandedRow.tsx | 6 ++++++ .../src/pages/ConsumerGroup/ResetOffsetDrawer.tsx | 3 +++ .../src/pages/TopicDetail/ConsumerGroupDetail.tsx | 6 ++++++ .../src/pages/TopicDetail/ResetOffsetDrawer.tsx | 8 ++++++++ 5 files changed, 24 insertions(+) diff --git a/km-console/packages/layout-clusters-fe/package.json b/km-console/packages/layout-clusters-fe/package.json index 62fe6f9c3..4453210ba 100644 --- a/km-console/packages/layout-clusters-fe/package.json +++ b/km-console/packages/layout-clusters-fe/package.json @@ -82,6 +82,7 @@ "@types/lodash": "^4.14.171", "@types/node": "^12.12.25", "@types/pubsub-js": "^1.5.18", + "pubsub-js": "^1.5.18", "@typescript-eslint/eslint-plugin": "4.13.0", "@typescript-eslint/parser": "4.13.0", "babel-eslint": "10.1.0", diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ExpandedRow.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ExpandedRow.tsx index 3e9519437..85ab81cc4 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ExpandedRow.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ExpandedRow.tsx @@ -8,6 +8,7 @@ import { IconFont } from '@knowdesign/icons'; import API from '@src/api/index'; import { hashDataParse } from '@src/constants/common'; const { Option } = Select; +import PubSub from 'pubsub-js' export interface MetricLine { createTime?: number; @@ -214,6 +215,11 @@ export const ExpandedRow: any = ({ record, groupName }: any) => { // getTopicGroupMetric(); // }, [sortObj]); + // 订阅重置offset成功的消息 + PubSub.subscribe('ConsumerGroup-ResetOffset', function(data){ + getTopicGroupMetric({}); + }) + useEffect(() => { const hashData = hashDataParse(location.hash); // if (!hashData.groupName) return; diff --git a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ResetOffsetDrawer.tsx b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ResetOffsetDrawer.tsx index 75cc390a0..f2fa3c83f 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ResetOffsetDrawer.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/ConsumerGroup/ResetOffsetDrawer.tsx @@ -4,6 +4,7 @@ import { useParams } from 'react-router-dom'; import EditTable from '../TestingProduce/component/EditTable'; import Api from '@src/api/index'; import moment from 'moment'; +import PubSub from 'pubsub-js' const CustomSelectResetTime = (props: { value?: string; onChange?: (val: Number | String) => void }) => { const { value, onChange } = props; @@ -106,6 +107,8 @@ export default (props: any) => { message: '重置offset成功', }); setVisible(false); + // 发布重置offset成功的消息 + PubSub.publish('ConsumerGroup-ResetOffset', '1'); } else { notification.error({ message: '重置offset失败', diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ConsumerGroupDetail.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ConsumerGroupDetail.tsx index bd502b1a2..0183dca54 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ConsumerGroupDetail.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ConsumerGroupDetail.tsx @@ -10,6 +10,7 @@ import { ClustersPermissionMap } from '../CommonConfig'; import ResetOffsetDrawer from './ResetOffsetDrawer'; import SwitchTab from '@src/components/SwitchTab'; import ContentWithCopy from '@src/components/CopyContent'; +import PubSub from "pubsub-js"; const { Option } = Select; @@ -335,6 +336,11 @@ export default (props: any) => { }); }, [visible]); +// 订阅重置offset成功的消息 + PubSub.subscribe('TopicDetail-ResetOffset', function(message, data){ + getTopicGroupMetric({hashData: data}); + }) + useEffect(() => { if (partitionList.length === 0) return; getTopicGroupMetricHistory(partitionList, hashData); diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ResetOffsetDrawer.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ResetOffsetDrawer.tsx index ed948e8c0..25674eaa6 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ResetOffsetDrawer.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/ResetOffsetDrawer.tsx @@ -4,6 +4,7 @@ import { useParams } from 'react-router-dom'; import EditTable from '../TestingProduce/component/EditTable'; import Api from '@src/api/index'; import moment from 'moment'; +import PubSub from "pubsub-js"; const CustomSelectResetTime = (props: { value?: string; onChange?: (val: Number | String) => void }) => { const { value, onChange } = props; @@ -106,6 +107,13 @@ export default (props: any) => { message: '重置offset成功', }); setResetOffsetVisible(false); + // 发布重置offset成功的消息 + PubSub.publish('TopicDetail-ResetOffset', + { + groupName: record.groupName, + topicName: record.topicName + } + ); } else { notification.error({ message: '重置offset失败', From c9308ee4f2267428a0693de633883670dcddff20 Mon Sep 17 00:00:00 2001 From: EricZeng Date: Mon, 23 Oct 2023 01:11:49 +0800 Subject: [PATCH 24/48] =?UTF-8?q?[Bugfix]=E4=BF=AE=E5=A4=8Dci=5Fbuild?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98=20(#1173)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- km-console/packages/layout-clusters-fe/package-lock.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/km-console/packages/layout-clusters-fe/package-lock.json b/km-console/packages/layout-clusters-fe/package-lock.json index 837de6ae8..2dca73a72 100644 --- a/km-console/packages/layout-clusters-fe/package-lock.json +++ b/km-console/packages/layout-clusters-fe/package-lock.json @@ -10004,6 +10004,12 @@ } } }, + "pubsub-js": { + "version": "1.9.4", + "resolved": "https://registry.npmmirror.com/pubsub-js/-/pubsub-js-1.9.4.tgz", + "integrity": "sha512-hJYpaDvPH4w8ZX/0Fdf9ma1AwRgU353GfbaVfPjfJQf1KxZ2iHaHl3fAUw1qlJIR5dr4F3RzjGaWohYUEyoh7A==", + "dev": true + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz", From c07e544c50faa53a7f89614c17ee4bc4dd510d77 Mon Sep 17 00:00:00 2001 From: erge <64293299+Wyb7290@users.noreply.github.com> Date: Tue, 7 Nov 2023 19:20:04 +0800 Subject: [PATCH 25/48] =?UTF-8?q?[Bugfix]Connect-JSON=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E7=9A=84JSON=E6=A0=BC=E5=BC=8F=E5=92=8C=E5=AE=98?= =?UTF-8?q?=E6=96=B9API=E7=9A=84=E6=A0=BC=E5=BC=8F=E4=B8=8D=E4=B8=80?= =?UTF-8?q?=E8=87=B4(#1048)=20(#1181)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 请不要在没有先创建Issue的情况下创建Pull Request。 ## 变更的目的是什么 XXXXX ## 简短的更新日志 XX ## 验证这一变化 XXXX 请遵循此清单,以帮助我们快速轻松地整合您的贡献: * [ ] 一个 PR(Pull Request的简写)只解决一个问题,禁止一个 PR 解决多个问题; * [ ] 确保 PR 有对应的 Issue(通常在您开始处理之前创建),除非是书写错误之类的琐碎更改不需要 Issue ; * [ ] 格式化 PR 及 Commit-Log 的标题及内容,例如 #861 。PS:Commit-Log 需要在 Git Commit 代码时进行填写,在 GitHub 上修改不了; * [ ] 编写足够详细的 PR 描述,以了解 PR 的作用、方式和原因; * [ ] 编写必要的单元测试来验证您的逻辑更正。如果提交了新功能或重大更改,请记住在 test 模块中添加 integration-test; * [ ] 确保编译通过,集成测试通过; --- .../src/pages/Connect/AddConnectorUseJSON.tsx | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx index b93513460..e06ede24e 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx @@ -10,7 +10,7 @@ const PLACEHOLDER = `配置格式如下 { "connectClusterName": "", // Connect Cluster 名称 - "configs": { // 具体配置项 + "config": { // 具体配置项 "name": "", "connector.class": "", "tasks.max": 1, @@ -47,7 +47,7 @@ export default forwardRef((props: any, ref) => { configs: JSON.stringify( { connectClusterName, - configs: defaultConfigs, + config: defaultConfigs, }, null, 2 @@ -63,13 +63,13 @@ export default forwardRef((props: any, ref) => { form.validateFields().then( (data) => { const postData = JSON.parse(data.configs); - postData.connectorName = postData.configs.name; + postData.connectorName = postData.config.name; postData.connectClusterId = connectClusters.find((cluster) => cluster.label === postData.connectClusterName).value; delete postData.connectClusterName; - Object.entries(postData.configs).forEach(([key, val]) => { + Object.entries(postData.config).forEach(([key, val]) => { if (val === null) { - delete postData.configs[key]; + delete postData.config[key]; } }); Utils.put(api.validateConnectorConfig, postData).then( @@ -198,20 +198,20 @@ export default forwardRef((props: any, ref) => { } } - if (!v.configs || typeof v.configs !== 'object') { - return Promise.reject('内容缺少 configs 字段或字段格式错误'); + if (!v.config || typeof v.config !== 'object') { + return Promise.reject('内容缺少 config 字段或字段格式错误'); } else { // 校验 connectorName 字段 - if (!v.configs.name) { - return Promise.reject('configs 字段下缺少 name 项'); + if (!v.config.name) { + return Promise.reject('config 字段下缺少 name 项'); } else { - if (type === 'edit' && v.configs.name !== defaultConfigs.name) { + if (type === 'edit' && v.config.name !== defaultConfigs.name) { return Promise.reject('编辑模式下不允许修改 name 字段'); } } - if (!v.configs['connector.class']) { - return Promise.reject('configs 字段下缺少 connector.class 项'); - } else if (type === 'edit' && v.configs['connector.class'] !== defaultConfigs['connector.class']) { + if (!v.config['connector.class']) { + return Promise.reject('config 字段下缺少 connector.class 项'); + } else if (type === 'edit' && v.config['connector.class'] !== defaultConfigs['connector.class']) { return Promise.reject('编辑模式下不允许修改 connector.class 字段'); } } @@ -219,13 +219,13 @@ export default forwardRef((props: any, ref) => { if (type === 'create') { // 异步校验 connector 名称是否重复 以及 className 是否存在 return Promise.all([ - Utils.request(api.isConnectorExist(connectClusterId, v.configs.name)), + Utils.request(api.isConnectorExist(connectClusterId, v.config.name)), Utils.request(api.getConnectorPlugins(connectClusterId)), ]).then( ([data, plugins]: [any, ConnectorPlugin[]]) => { return data?.exist ? Promise.reject('name 与已有 Connector 重复') - : plugins.every((plugin) => plugin.className !== v.configs['connector.class']) + : plugins.every((plugin) => plugin.className !== v.config['connector.class']) ? Promise.reject('该 connectCluster 下不存在 connector.class 项配置的插件') : Promise.resolve(); }, From 530219a3172c59963bd051ae9ba9937dc003b282 Mon Sep 17 00:00:00 2001 From: Peng <71620349+PenceXie@users.noreply.github.com> Date: Wed, 8 Nov 2023 14:07:58 +0800 Subject: [PATCH 26/48] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d95a05874..c22f65d55 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,8 @@ **点击 [这里](https://doc.knowstreaming.com/product),也可以从官网获取到更多文档** - +- [产品官网https://knowstreaming.com](https://knowstreaming.com) +- [产品demo] From 38366809f1bc4d1f189c6f3289259419543ac1c7 Mon Sep 17 00:00:00 2001 From: Peng <71620349+PenceXie@users.noreply.github.com> Date: Wed, 8 Nov 2023 14:10:40 +0800 Subject: [PATCH 27/48] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c22f65d55..950491d5b 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,10 @@ **点击 [这里](https://doc.knowstreaming.com/product),也可以从官网获取到更多文档** -- [产品官网https://knowstreaming.com](https://knowstreaming.com) -- [产品demo] +**`产品网址`** +- [产品官网:https://knowstreaming.com](https://knowstreaming.com) +- [体验环境:admin/admin](https://demo.knowstreaming.com) From 65f8beef32246cfea059cf2e5470384bcdc8c3cc Mon Sep 17 00:00:00 2001 From: Peng <71620349+PenceXie@users.noreply.github.com> Date: Wed, 8 Nov 2023 14:11:59 +0800 Subject: [PATCH 28/48] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 950491d5b..232079242 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ **`产品网址`** - [产品官网:https://knowstreaming.com](https://knowstreaming.com) -- [体验环境:admin/admin](https://demo.knowstreaming.com) +- [体验环境:https://demo.knowstreaming.com](https://demo.knowstreaming.com),登陆账号:admin/admin From 251f7f711094649368d2139ab903e45b22e49ca2 Mon Sep 17 00:00:00 2001 From: "qiao.zeng" Date: Sun, 12 Nov 2023 15:06:10 +0800 Subject: [PATCH 29/48] =?UTF-8?q?[Bugfix]=E4=BF=AE=E5=A4=8DTruncate?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=B8=8D=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../km/biz/topic/impl/OpTopicManagerImpl.java | 67 +++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/topic/impl/OpTopicManagerImpl.java b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/topic/impl/OpTopicManagerImpl.java index 22d204ea5..424594472 100644 --- a/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/topic/impl/OpTopicManagerImpl.java +++ b/km-biz/src/main/java/com/xiaojukeji/know/streaming/km/biz/topic/impl/OpTopicManagerImpl.java @@ -7,6 +7,7 @@ import com.xiaojukeji.know.streaming.km.common.bean.dto.topic.TopicExpansionDTO; import com.xiaojukeji.know.streaming.km.common.bean.entity.broker.Broker; import com.xiaojukeji.know.streaming.km.common.bean.entity.cluster.ClusterPhy; +import com.xiaojukeji.know.streaming.km.common.bean.entity.param.config.KafkaTopicConfigParam; import com.xiaojukeji.know.streaming.km.common.bean.entity.param.topic.TopicCreateParam; import com.xiaojukeji.know.streaming.km.common.bean.entity.param.topic.TopicParam; import com.xiaojukeji.know.streaming.km.common.bean.entity.param.topic.TopicPartitionExpandParam; @@ -17,17 +18,17 @@ import com.xiaojukeji.know.streaming.km.common.bean.entity.topic.Topic; import com.xiaojukeji.know.streaming.km.common.constant.KafkaConstant; import com.xiaojukeji.know.streaming.km.common.constant.MsgConstant; -import com.xiaojukeji.know.streaming.km.common.utils.BackoffUtils; -import com.xiaojukeji.know.streaming.km.common.utils.FutureUtil; -import com.xiaojukeji.know.streaming.km.common.utils.ValidateUtils; +import com.xiaojukeji.know.streaming.km.common.utils.*; import com.xiaojukeji.know.streaming.km.common.utils.kafka.KafkaReplicaAssignUtil; import com.xiaojukeji.know.streaming.km.core.service.broker.BrokerService; import com.xiaojukeji.know.streaming.km.core.service.cluster.ClusterPhyService; import com.xiaojukeji.know.streaming.km.core.service.partition.PartitionService; import com.xiaojukeji.know.streaming.km.core.service.topic.OpTopicService; +import com.xiaojukeji.know.streaming.km.core.service.topic.TopicConfigService; import com.xiaojukeji.know.streaming.km.core.service.topic.TopicService; import kafka.admin.AdminUtils; import kafka.admin.BrokerMetadata; +import org.apache.kafka.common.config.TopicConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -61,6 +62,9 @@ public class OpTopicManagerImpl implements OpTopicManager { @Autowired private PartitionService partitionService; + @Autowired + private TopicConfigService topicConfigService; + @Override public Result createTopic(TopicCreateDTO dto, String operator) { log.info("method=createTopic||param={}||operator={}.", dto, operator); @@ -160,10 +164,27 @@ public Result expandTopic(TopicExpansionDTO dto, String operator) { @Override public Result truncateTopic(Long clusterPhyId, String topicName, String operator) { + // 增加delete配置 + Result> rt = this.addDeleteConfigIfNotExist(clusterPhyId, topicName, operator); + if (rt.failed()) { + log.error("method=truncateTopic||clusterPhyId={}||topicName={}||operator={}||result={}||msg=get config from kafka failed", clusterPhyId, topicName, operator, rt); + return Result.buildFromIgnoreData(rt); + } + // 清空Topic Result rv = opTopicService.truncateTopic(new TopicTruncateParam(clusterPhyId, topicName, KafkaConstant.TOPICK_TRUNCATE_DEFAULT_OFFSET), operator); if (rv.failed()) { - return rv; + log.error("method=truncateTopic||clusterPhyId={}||topicName={}||originConfig={}||operator={}||result={}||msg=truncate topic failed", clusterPhyId, topicName, rt.getData().v2(), operator, rv); + // config被修改了,则错误提示需要提醒一下,否则直接返回错误 + return rt.getData().v1() ? Result.buildFailure(rv.getCode(), rv.getMessage() + "\t\n" + String.format("Topic的CleanupPolicy已被修改,需要手动恢复为%s", rt.getData().v2())) : rv; + } + + // 恢复compact配置 + rv = this.recoverConfigIfChanged(clusterPhyId, topicName, rt.getData().v1(), rt.getData().v2(), operator); + if (rv.failed()) { + log.error("method=truncateTopic||clusterPhyId={}||topicName={}||originConfig={}||operator={}||result={}||msg=truncate topic success but recover config failed", clusterPhyId, topicName, rt.getData().v2(), operator, rv); + // config被修改了,则错误提示需要提醒一下,否则直接返回错误 + return Result.buildFailure(rv.getCode(), String.format("Topic清空操作已成功,但是恢复CleanupPolicy配置失败,需要手动恢复为%s。", rt.getData().v2()) + "\t\n" + rv.getMessage()); } return Result.buildSuc(); @@ -171,6 +192,44 @@ public Result truncateTopic(Long clusterPhyId, String topicName, String op /**************************************************** private method ****************************************************/ + private Result> addDeleteConfigIfNotExist(Long clusterPhyId, String topicName, String operator) { + // 获取Topic配置 + Result> configMapResult = topicConfigService.getTopicConfigFromKafka(clusterPhyId, topicName); + if (configMapResult.failed()) { + return Result.buildFromIgnoreData(configMapResult); + } + + String cleanupPolicyValue = configMapResult.getData().getOrDefault(TopicConfig.CLEANUP_POLICY_CONFIG, ""); + List cleanupPolicyValueList = CommonUtils.string2StrList(cleanupPolicyValue); + if (cleanupPolicyValueList.size() == 1 && cleanupPolicyValueList.contains(TopicConfig.CLEANUP_POLICY_DELETE)) { + // 不需要修改 + return Result.buildSuc(new Tuple<>(Boolean.FALSE, cleanupPolicyValue)); + } + + Map changedConfigMap = new HashMap<>(1); + changedConfigMap.put(TopicConfig.CLEANUP_POLICY_CONFIG, TopicConfig.CLEANUP_POLICY_DELETE); + + Result rv = topicConfigService.modifyTopicConfig(new KafkaTopicConfigParam(clusterPhyId, topicName, changedConfigMap), operator); + if (rv.failed()) { + // 修改失败 + return Result.buildFromIgnoreData(rv); + } + + return Result.buildSuc(new Tuple<>(Boolean.TRUE, cleanupPolicyValue)); + } + + private Result recoverConfigIfChanged(Long clusterPhyId, String topicName, Boolean changed, String originValue, String operator) { + if (!changed) { + // 没有修改,直接返回 + return Result.buildSuc(); + } + + // 恢复配置 + Map changedConfigMap = new HashMap<>(1); + changedConfigMap.put(TopicConfig.CLEANUP_POLICY_CONFIG, originValue); + + return topicConfigService.modifyTopicConfig(new KafkaTopicConfigParam(clusterPhyId, topicName, changedConfigMap), operator); + } private Seq buildBrokerMetadataSeq(Long clusterPhyId, final List selectedBrokerIdList) { // 选取Broker列表 From e24a582067e3ce9b1d7886b03556872ce1a99716 Mon Sep 17 00:00:00 2001 From: "qiao.zeng" Date: Sun, 12 Nov 2023 15:25:23 +0800 Subject: [PATCH 30/48] =?UTF-8?q?[Doc]=E4=BF=AE=E6=94=B9action=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci_build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_build.yml b/.github/workflows/ci_build.yml index 073d46522..2544c5706 100644 --- a/.github/workflows/ci_build.yml +++ b/.github/workflows/ci_build.yml @@ -2,9 +2,9 @@ name: KnowStreaming Build on: push: - branches: [ "master", "ve_3.x", "ve_demo_3.x" ] + branches: [ "*" ] pull_request: - branches: [ "master", "ve_3.x", "ve_demo_3.x" ] + branches: [ "*" ] jobs: build: From ab6afe6dbc5b1ec7514921d2121634e585fa0a6f Mon Sep 17 00:00:00 2001 From: Peng <71620349+PenceXie@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:10:51 +0800 Subject: [PATCH 31/48] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 232079242..ac9415bec 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ PS: 提问请尽量把问题一次性描述清楚,并告知环境信息情况 **`2、微信群`** -微信加群:添加`mike_zhangliang`、`PenceXie` 、`szzdzhp001`的微信号备注KnowStreaming加群。 +微信加群:添加`PenceXie` 、`szzdzhp001`的微信号备注KnowStreaming加群。
加群之前有劳点一下 star,一个小小的 star 是对KnowStreaming作者们努力建设社区的动力。 From 1369e7b9eb890602bdb91a2020ffcfa89886929c Mon Sep 17 00:00:00 2001 From: HuYueeer <40758588+Huyueeer@users.noreply.github.com> Date: Sat, 25 Nov 2023 09:22:41 +0800 Subject: [PATCH 32/48] FAQ (#1189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增依赖elasticsearch8.0以上版本出现指标信息不显示的解决方法 --- docs/user_guide/faq.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/user_guide/faq.md b/docs/user_guide/faq.md index 2897bf695..de20e3dbd 100644 --- a/docs/user_guide/faq.md +++ b/docs/user_guide/faq.md @@ -22,6 +22,7 @@ - [16、JMX连接失败怎么办](#16jmx连接失败怎么办) - [17、zk监控无数据问题](#17zk监控无数据问题) - [18、启动失败,报NoClassDefFoundError如何解决](#18启动失败报noclassdeffounderror如何解决) + - [19、依赖ElasticSearch 8.0以上版本部署后指标信息无法正常显示如何解决] ## 1、支持哪些 Kafka 版本? @@ -306,4 +307,15 @@ at org.springframework.beans.factory.support.ConstructorResolver.instantiate(Con 如果在在 `Windows`、`Mac`、`CentOS` 这几个操作系统下也出现了启动失败的问题,可以重试2-3次看是否还是启动失败,或者换一台机器试试。 +## 依赖ElasticSearch 8.0以上版本部署后指标信息无法正常显示如何解决 +**错误现象** +```log +Warnings: [299 Elasticsearch-8.9.1-a813d015ef1826148d9d389bd1c0d781c6e349f0 "Legacy index templates are deprecated in favor of composable templates."] +``` +**问题原因** +1. ES8.0和ES7.0版本存在Template模式的差异,建议使用 /_index_template 端点来管理模板; +2. ES java client在此版本的行为很奇怪表现为读取数据为空; + +**解决方法** +修改`es_template_create.sh`脚本中所有的`/_template`为`/_index_template`后执行即可。 From af82c2e615a731b07604b959d175b96da36c67f1 Mon Sep 17 00:00:00 2001 From: jiangminbing Date: Sat, 25 Nov 2023 09:27:43 +0800 Subject: [PATCH 33/48] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8DOverview?= =?UTF-8?q?=E6=8C=87=E6=A0=87=E6=96=87=E5=AD=97=E9=94=99=E8=AF=AF=20(#1190?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Bugfix] 修复Overview指标文字错误 (#1150) Co-authored-by: jiangmb --- ...07\346\240\207\350\257\264\346\230\216.md" | 94 +++++++++---------- .../kafka/ClusterMetricVersionItems.java | 2 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git "a/docs/dev_guide/\346\214\207\346\240\207\350\257\264\346\230\216.md" "b/docs/dev_guide/\346\214\207\346\240\207\350\257\264\346\230\216.md" index 1eb9a94b8..9e6101da5 100644 --- "a/docs/dev_guide/\346\214\207\346\240\207\350\257\264\346\230\216.md" +++ "b/docs/dev_guide/\346\214\207\346\240\207\350\257\264\346\230\216.md" @@ -6,72 +6,72 @@ ### 3.3.1、Cluster 指标 -| 指标名称 | 指标单位 | 指标含义 | kafka 版本 | 企业/开源版指标 | -| ------------------------- | -------- | ------------------------------------ | ---------------- | --------------- | -| HealthScore | 分 | 集群总体的健康分 | 全部版本 | 开源版 | -| HealthCheckPassed | 个 | 集群总体健康检查通过数 | 全部版本 | 开源版 | -| HealthCheckTotal | 个 | 集群总体健康检查总数 | 全部版本 | 开源版 | +| 指标名称 | 指标单位 | 指标含义 | kafka 版本 | 企业/开源版指标 | +| ------------------------- | -------- |--------------------------------| ---------------- | --------------- | +| HealthScore | 分 | 集群总体的健康分 | 全部版本 | 开源版 | +| HealthCheckPassed | 个 | 集群总体健康检查通过数 | 全部版本 | 开源版 | +| HealthCheckTotal | 个 | 集群总体健康检查总数 | 全部版本 | 开源版 | | HealthScore_Topics | 分 | 集群 Topics 的健康分 | 全部版本 | 开源版 | -| HealthCheckPassed_Topics | 个 | 集群 Topics 健康检查通过数 | 全部版本 | 开源版 | -| HealthCheckTotal_Topics | 个 | 集群 Topics 健康检查总数 | 全部版本 | 开源版 | +| HealthCheckPassed_Topics | 个 | 集群 Topics 健康检查通过数 | 全部版本 | 开源版 | +| HealthCheckTotal_Topics | 个 | 集群 Topics 健康检查总数 | 全部版本 | 开源版 | | HealthScore_Brokers | 分 | 集群 Brokers 的健康分 | 全部版本 | 开源版 | -| HealthCheckPassed_Brokers | 个 | 集群 Brokers 健康检查通过数 | 全部版本 | 开源版 | -| HealthCheckTotal_Brokers | 个 | 集群 Brokers 健康检查总数 | 全部版本 | 开源版 | +| HealthCheckPassed_Brokers | 个 | 集群 Brokers 健康检查通过数 | 全部版本 | 开源版 | +| HealthCheckTotal_Brokers | 个 | 集群 Brokers 健康检查总数 | 全部版本 | 开源版 | | HealthScore_Groups | 分 | 集群 Groups 的健康分 | 全部版本 | 开源版 | -| HealthCheckPassed_Groups | 个 | 集群 Groups 健康检查总数 | 全部版本 | 开源版 | -| HealthCheckTotal_Groups | 个 | 集群 Groups 健康检查总数 | 全部版本 | 开源版 | -| HealthScore_Cluster | 分 | 集群自身的健康分 | 全部版本 | 开源版 | -| HealthCheckPassed_Cluster | 个 | 集群自身健康检查通过数 | 全部版本 | 开源版 | -| HealthCheckTotal_Cluster | 个 | 集群自身健康检查总数 | 全部版本 | 开源版 | -| TotalRequestQueueSize | 个 | 集群中总的请求队列数 | 全部版本 | 开源版 | -| TotalResponseQueueSize | 个 | 集群中总的响应队列数 | 全部版本 | 开源版 | +| HealthCheckPassed_Groups | 个 | 集群 Groups 健康检查总数 | 全部版本 | 开源版 | +| HealthCheckTotal_Groups | 个 | 集群 Groups 健康检查总数 | 全部版本 | 开源版 | +| HealthScore_Cluster | 分 | 集群自身的健康分 | 全部版本 | 开源版 | +| HealthCheckPassed_Cluster | 个 | 集群自身健康检查通过数 | 全部版本 | 开源版 | +| HealthCheckTotal_Cluster | 个 | 集群自身健康检查总数 | 全部版本 | 开源版 | +| TotalRequestQueueSize | 个 | 集群中总的请求队列数 | 全部版本 | 开源版 | +| TotalResponseQueueSize | 个 | 集群中总的响应队列数 | 全部版本 | 开源版 | | EventQueueSize | 个 | 集群中 Controller 的 EventQueue 大小 | 2.0.0 及以上版本 | 开源版 | -| ActiveControllerCount | 个 | 集群中存活的 Controller 数 | 全部版本 | 开源版 | -| TotalProduceRequests | 个 | 集群中的 Produce 每秒请求数 | 全部版本 | 开源版 | -| TotalLogSize | byte | 集群总的已使用的磁盘大小 | 全部版本 | 开源版 | -| ConnectionsCount | 个 | 集群的连接(Connections)个数 | 全部版本 | 开源版 | -| Zookeepers | 个 | 集群中存活的 zk 节点个数 | 全部版本 | 开源版 | +| ActiveControllerCount | 个 | 集群中存活的 Controller 数 | 全部版本 | 开源版 | +| TotalProduceRequests | 个 | 集群中的 Produce 每秒请求数 | 全部版本 | 开源版 | +| TotalLogSize | byte | 集群总的已使用的磁盘大小 | 全部版本 | 开源版 | +| ConnectionsCount | 个 | 集群的连接(Connections)个数 | 全部版本 | 开源版 | +| Zookeepers | 个 | 集群中存活的 zk 节点个数 | 全部版本 | 开源版 | | ZookeepersAvailable | 是/否 | ZK 地址是否合法 | 全部版本 | 开源版 | | Brokers | 个 | 集群的 broker 的总数 | 全部版本 | 开源版 | -| BrokersAlive | 个 | 集群的 broker 的存活数 | 全部版本 | 开源版 | -| BrokersNotAlive | 个 | 集群的 broker 的未存活数 | 全部版本 | 开源版 | +| BrokersAlive | 个 | 集群的 broker 的存活数 | 全部版本 | 开源版 | +| BrokersNotAlive | 个 | 集群的 broker 的未存活数 | 全部版本 | 开源版 | | Replicas | 个 | 集群中 Replica 的总数 | 全部版本 | 开源版 | | Topics | 个 | 集群中 Topic 的总数 | 全部版本 | 开源版 | -| Partitions | 个 | 集群的 Partitions 总数 | 全部版本 | 开源版 | +| Partitions | 个 | 集群的 Partitions 总数 | 全部版本 | 开源版 | | PartitionNoLeader | 个 | 集群中的 PartitionNoLeader 总数 | 全部版本 | 开源版 | -| PartitionMinISR_S | 个 | 集群中的小于 PartitionMinISR 总数 | 全部版本 | 开源版 | -| PartitionMinISR_E | 个 | 集群中的等于 PartitionMinISR 总数 | 全部版本 | 开源版 | -| PartitionURP | 个 | 集群中的未同步的 Partition 总数 | 全部版本 | 开源版 | -| MessagesIn | 条/s | 集群每条消息写入条数 | 全部版本 | 开源版 | -| Messages | 条 | 集群总的消息条数 | 全部版本 | 开源版 | -| LeaderMessages | 条 | 集群中 leader 总的消息条数 | 全部版本 | 开源版 | -| BytesIn | byte/s | 集群的每秒写入字节数 | 全部版本 | 开源版 | -| BytesIn_min_5 | byte/s | 集群的每秒写入字节数,5 分钟均值 | 全部版本 | 开源版 | -| BytesIn_min_15 | byte/s | 集群的每秒写入字节数,15 分钟均值 | 全部版本 | 开源版 | -| BytesOut | byte/s | 集群的每秒流出字节数 | 全部版本 | 开源版 | -| BytesOut_min_5 | byte/s | 集群的每秒流出字节数,5 分钟均值 | 全部版本 | 开源版 | -| BytesOut_min_15 | byte/s | 集群的每秒流出字节数,15 分钟均值 | 全部版本 | 开源版 | +| PartitionMinISR_S | 个 | 集群中的小于 PartitionMinISR 总数 | 全部版本 | 开源版 | +| PartitionMinISR_E | 个 | 集群中的等于 PartitionMinISR 总数 | 全部版本 | 开源版 | +| PartitionURP | 个 | 集群中的未同步的 Partition 总数 | 全部版本 | 开源版 | +| MessagesIn | 条/s | 集群每秒消息写入条数 | 全部版本 | 开源版 | +| Messages | 条 | 集群总的消息条数 | 全部版本 | 开源版 | +| LeaderMessages | 条 | 集群中 leader 总的消息条数 | 全部版本 | 开源版 | +| BytesIn | byte/s | 集群的每秒写入字节数 | 全部版本 | 开源版 | +| BytesIn_min_5 | byte/s | 集群的每秒写入字节数,5 分钟均值 | 全部版本 | 开源版 | +| BytesIn_min_15 | byte/s | 集群的每秒写入字节数,15 分钟均值 | 全部版本 | 开源版 | +| BytesOut | byte/s | 集群的每秒流出字节数 | 全部版本 | 开源版 | +| BytesOut_min_5 | byte/s | 集群的每秒流出字节数,5 分钟均值 | 全部版本 | 开源版 | +| BytesOut_min_15 | byte/s | 集群的每秒流出字节数,15 分钟均值 | 全部版本 | 开源版 | | Groups | 个 | 集群中 Group 的总数 | 全部版本 | 开源版 | | GroupActives | 个 | 集群中 ActiveGroup 的总数 | 全部版本 | 开源版 | | GroupEmptys | 个 | 集群中 EmptyGroup 的总数 | 全部版本 | 开源版 | | GroupRebalances | 个 | 集群中 RebalanceGroup 的总数 | 全部版本 | 开源版 | | GroupDeads | 个 | 集群中 DeadGroup 的总数 | 全部版本 | 开源版 | -| Alive | 是/否 | 集群是否存活,1:存活;0:没有存活 | 全部版本 | 开源版 | -| AclEnable | 是/否 | 集群是否开启 Acl,1:是;0:否 | 全部版本 | 开源版 | -| Acls | 个 | ACL 数 | 全部版本 | 开源版 | -| AclUsers | 个 | ACL-KafkaUser 数 | 全部版本 | 开源版 | -| AclTopics | 个 | ACL-Topic 数 | 全部版本 | 开源版 | -| AclGroups | 个 | ACL-Group 数 | 全部版本 | 开源版 | +| Alive | 是/否 | 集群是否存活,1:存活;0:没有存活 | 全部版本 | 开源版 | +| AclEnable | 是/否 | 集群是否开启 Acl,1:是;0:否 | 全部版本 | 开源版 | +| Acls | 个 | ACL 数 | 全部版本 | 开源版 | +| AclUsers | 个 | ACL-KafkaUser 数 | 全部版本 | 开源版 | +| AclTopics | 个 | ACL-Topic 数 | 全部版本 | 开源版 | +| AclGroups | 个 | ACL-Group 数 | 全部版本 | 开源版 | | Jobs | 个 | 集群任务总数 | 全部版本 | 开源版 | | JobsRunning | 个 | 集群 running 任务总数 | 全部版本 | 开源版 | | JobsWaiting | 个 | 集群 waiting 任务总数 | 全部版本 | 开源版 | | JobsSuccess | 个 | 集群 success 任务总数 | 全部版本 | 开源版 | | JobsFailed | 个 | 集群 failed 任务总数 | 全部版本 | 开源版 | -| LoadReBalanceEnable | 是/否 | 是否开启均衡, 1:是;0:否 | 全部版本 | 企业版 | -| LoadReBalanceCpu | 是/否 | CPU 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | -| LoadReBalanceNwIn | 是/否 | BytesIn 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | -| LoadReBalanceNwOut | 是/否 | BytesOut 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | -| LoadReBalanceDisk | 是/否 | Disk 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | +| LoadReBalanceEnable | 是/否 | 是否开启均衡, 1:是;0:否 | 全部版本 | 企业版 | +| LoadReBalanceCpu | 是/否 | CPU 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | +| LoadReBalanceNwIn | 是/否 | BytesIn 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | +| LoadReBalanceNwOut | 是/否 | BytesOut 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | +| LoadReBalanceDisk | 是/否 | Disk 是否均衡, 1:是;0:否 | 全部版本 | 企业版 | ### 3.3.2、Broker 指标 diff --git a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/kafka/ClusterMetricVersionItems.java b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/kafka/ClusterMetricVersionItems.java index cefe8930e..dbcdac57f 100644 --- a/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/kafka/ClusterMetricVersionItems.java +++ b/km-core/src/main/java/com/xiaojukeji/know/streaming/km/core/service/version/metrics/kafka/ClusterMetricVersionItems.java @@ -299,7 +299,7 @@ public List init(){ // MessagesIn 指标 itemList.add( buildAllVersionsItem() - .name(CLUSTER_METRIC_MESSAGES_IN).unit("条/s").desc("集群每条消息写入条数").category(CATEGORY_CLUSTER) + .name(CLUSTER_METRIC_MESSAGES_IN).unit("条/s").desc("集群每秒消息写入条数").category(CATEGORY_CLUSTER) .extend( buildJMXMethodExtend( CLUSTER_METHOD_GET_METRIC_FROM_KAFKA_BY_TOTAL_BROKERS_JMX ) .jmxObjectName( JMX_SERVER_BROKER_MESSAGES_IN ).jmxAttribute(RATE_MIN_1))); From e80f8086d458cc29254fab43b2420a7600340120 Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 26 Nov 2023 16:18:39 +0800 Subject: [PATCH 34/48] =?UTF-8?q?[Bugfix]=E4=BC=98=E5=8C=96=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E5=AD=90=E5=BA=94=E7=94=A8=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=AD=A3=E5=B8=B8=E5=90=AF=E5=8A=A8(#1167)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../packages/config-manager-fe/config/webpack.common.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/km-console/packages/config-manager-fe/config/webpack.common.js b/km-console/packages/config-manager-fe/config/webpack.common.js index cef88e615..7521137bc 100644 --- a/km-console/packages/config-manager-fe/config/webpack.common.js +++ b/km-console/packages/config-manager-fe/config/webpack.common.js @@ -16,6 +16,13 @@ const babelOptions = { cacheDirectory: true, babelrc: false, presets: [require.resolve('@babel/preset-env'), require.resolve('@babel/preset-typescript'), require.resolve('@babel/preset-react')], + overrides: [ + // TODO:编译时需要做的事情更多,应该只针对目标第三方库 + { + include: './node_modules', + sourceType: 'unambiguous' + } + ], plugins: [ [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }], [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], From 8a95401364cf100c6ea59d0f8a9d37315d5119d1 Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 26 Nov 2023 16:21:14 +0800 Subject: [PATCH 35/48] =?UTF-8?q?[Optimize]security=E4=B8=8B=E7=9A=84users?= =?UTF-8?q?=E3=80=81acls=E6=8E=A5=E5=85=A5=E8=BF=9B=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=AE=A1=E7=90=86(#1089)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/CommonConfig.tsx | 10 ++++-- .../src/pages/SecurityACLs/index.tsx | 33 +++++++++++-------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx index 722d04e67..5c0ded8d6 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/CommonConfig.tsx @@ -48,6 +48,12 @@ export enum ClustersPermissionMap { CONNECTOR_DELETE = 'Connector-删除', CONNECTOR_RESTART = 'Connector-重启', CONNECTOR_STOP_RESUME = 'Connector-暂停&恢复', + // Security + SECURITY_ACL_ADD = 'Security-ACL新增', + SECURITY_ACL_DELETE = 'Security-ACL删除', + SECURITY_USER_ADD = 'Security-User新增', + SECURITY_USER_DELETE = 'Security-User删除', + SECURITY_USER_EDIT_PASSWORD = 'Security-User修改密码', } export interface PermissionNode { @@ -98,9 +104,7 @@ const CommonConfig = () => { clustersPermissions.childList.forEach((node: PermissionNode) => node.has && userPermissions.push(node.permissionName)); // 获取用户在系统管理拥有的权限 - const configPermissions = userPermissionTree.find( - (sys: PermissionNode) => sys.permissionName === ClustersPermissionMap.SYS_MANAGE - ); + const configPermissions = userPermissionTree.find((sys: PermissionNode) => sys.permissionName === ClustersPermissionMap.SYS_MANAGE); configPermissions && configPermissions.childList.forEach((node: PermissionNode) => node.has && userPermissions.push(node.permissionName)); diff --git a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx index 9919afdda..46befe501 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/index.tsx @@ -14,6 +14,7 @@ import AddACLDrawer, { RESOURCE_TO_OPERATIONS_MAP, RESOURCE_MAP_KEYS, } from './EditDrawer'; +import { ClustersPermissionMap } from '../CommonConfig'; import './index.less'; const { confirm } = Modal; @@ -105,7 +106,7 @@ const SecurityACLs = (): JSX.Element => { }; const columns = () => { - const baseColumns = [ + const baseColumns: any = [ { title: 'Principal', dataIndex: 'kafkaUser', @@ -143,7 +144,9 @@ const SecurityACLs = (): JSX.Element => { title: 'Host', dataIndex: 'aclClientHost', }, - { + ]; + if (global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_ACL_DELETE)) { + baseColumns.push({ title: '操作', dataIndex: '', width: 120, @@ -156,8 +159,8 @@ const SecurityACLs = (): JSX.Element => { ); }, - }, - ]; + }); + } return baseColumns; }; @@ -238,15 +241,19 @@ const SecurityACLs = (): JSX.Element => { -
- -
+ {global.hasPermission && global.hasPermission(ClustersPermissionMap.SECURITY_ACL_ADD) ? ( +
+ +
+ ) : ( + <> + )} Date: Sun, 26 Nov 2023 16:23:12 +0800 Subject: [PATCH 36/48] =?UTF-8?q?[BugFix]=E4=BF=AE=E5=A4=8DTopic=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=B1=95=E7=A4=BA=EF=BC=8Coffset=E4=B8=BA0=E4=B8=8D?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98(#996)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layout-clusters-fe/src/pages/TopicDetail/config.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx index a6cdbc251..70055b2da 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/TopicDetail/config.tsx @@ -82,7 +82,7 @@ export const getTopicMessagesColmns = () => { dataIndex: 'offset', key: 'offset', sorter: true, - render: (t: number) => (+t ? t.toLocaleString() : '-'), + render: (t: number) => (+t || +t === 0 ? t.toLocaleString() : '-'), // TODO: 千分位展示 }, { title: 'Timestamp', From 592dee884a5a4a67e0f7991e9e8f6123fd618e19 Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 26 Nov 2023 16:25:00 +0800 Subject: [PATCH 37/48] =?UTF-8?q?[Optimize]Connect=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=94=A8=E6=88=B7=E9=83=BD=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E9=87=8D=E5=90=AF=E3=80=81=E7=BC=96=E8=BE=91=E3=80=81=E5=88=A0?= =?UTF-8?q?=E9=99=A4(#1050)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/Connect/config.tsx | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx index 84c2b5190..d6d12bfab 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/config.tsx @@ -315,6 +315,7 @@ export const getWorkersColumns = (arg?: any) => { // Detail export const getConnectorsDetailColumns = (arg?: any) => { + const [global] = AppContainer.useGlobalValue(); const columns = [ { title: 'Task ID', @@ -363,16 +364,20 @@ export const getConnectorsDetailColumns = (arg?: any) => { render: (_t: any, r: any) => { return (
- arg?.retryOption(r.taskId)} - // onCancel={cancel} - okText="是" - cancelText="否" - overlayClassName="connect-popconfirm" - > - 重试 - + {global.hasPermission(ClustersPermissionMap.CONNECTOR_RESTART) ? ( + arg?.retryOption(r.taskId)} + // onCancel={cancel} + okText="是" + cancelText="否" + overlayClassName="connect-popconfirm" + > + 重试 + + ) : ( + <> + )}
); }, From 8b30f78744791a504cc50074c9ed5636bed79e8a Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 26 Nov 2023 16:26:06 +0800 Subject: [PATCH 38/48] =?UTF-8?q?[Optimize]=E6=9D=83=E9=99=90=E6=96=B0?= =?UTF-8?q?=E5=A2=9EACL=EF=BC=8C=E8=87=AA=E5=AE=9A=E4=B9=89=E6=9D=83?= =?UTF-8?q?=E9=99=90=E9=85=8D=E7=BD=AE=EF=BC=8C=E8=B5=84=E6=BA=90Transacti?= =?UTF-8?q?onalId=E4=BC=98=E5=8C=96(#1160)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/SecurityACLs/EditDrawer.tsx | 100 +++++++++++------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/EditDrawer.tsx b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/EditDrawer.tsx index e155f3dad..1cc3a9099 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/EditDrawer.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/SecurityACLs/EditDrawer.tsx @@ -132,17 +132,35 @@ const AddDrawer = forwardRef((_, ref) => { form.validateFields().then((formData) => { const submitData = []; const { configType, principle, kafkaUser } = formData; - if (configType === 'custom') { // 1. 自定义权限 // TODO: 需要和后端联调 - const { resourceType, resourcePatternType, aclPermissionType, aclOperation, aclClientHost } = formData; + const { + resourceType, + resourcePatternType, + aclPermissionType, + aclOperation, + aclClientHost, + cluster, + topicName, + topicPatternType, + groupName, + groupPatternType, + transactionalId, + transactionalIdPatternType, + } = formData; submitData.push({ clusterId, kafkaUser: principle === 'all' ? '*' : kafkaUser, resourceType, - resourcePatternType, - resourceName: '*', + resourcePatternType: cluster + ? 3 + : topicPatternType + ? topicPatternType + : groupPatternType + ? groupPatternType + : transactionalIdPatternType, + resourceName: cluster ? cluster : topicName ? topicName : groupName ? groupName : transactionalId, aclPermissionType, aclOperation, aclClientHost, @@ -348,37 +366,43 @@ const AddDrawer = forwardRef((_, ref) => { {({ getFieldValue }) => getFieldValue(`${type}Principle`) === 'special' ? ( - ({ - validator: (rule: any, value: string) => { - if (!value) { - return Promise.reject(`${UpperCaseType}Name 不能为空`); - } - if (type === 'topic' && getFieldValue(`${type}PatternType`) === ACL_PATTERN_TYPE['Literal']) { - return Utils.request(api.getTopicMetadata(clusterId as any, value)).then((res: any) => { - return res?.exist ? Promise.resolve() : Promise.reject('该 Topic 不存在'); - }); + type !== 'transactionalId' ? ( + ({ + validator: (rule: any, value: string) => { + if (!value) { + return Promise.reject(`${UpperCaseType}Name 不能为空`); + } + if (type === 'topic' && getFieldValue(`${type}PatternType`) === ACL_PATTERN_TYPE['Literal']) { + return Utils.request(api.getTopicMetadata(clusterId as any, value)).then((res: any) => { + return res?.exist ? Promise.resolve() : Promise.reject('该 Topic 不存在'); + }); + } + return Promise.resolve(); + }, + }), + ]} + > + { + if (option?.value.includes(value)) { + return true; } - return Promise.resolve(); - }, - }), - ]} - > - { - if (option?.value.includes(value)) { - return true; - } - return false; - }} - options={type === 'topic' ? topicMetaData : groupMetaData} - placeholder={`请输入 ${type}Name`} - /> - + return false; + }} + options={type === 'topic' ? topicMetaData : groupMetaData} + placeholder={`请输入 ${type}Name`} + /> + + ) : ( + + + + ) ) : null } @@ -400,7 +424,7 @@ const AddDrawer = forwardRef((_, ref) => { Deny - { Literal Prefixed - + */} { {({ getFieldValue }) => { const type = getFieldValue('resourceType'); - if (type === ACL_RESOURCE_TYPE['Cluster'] || type === ACL_RESOURCE_TYPE['TransactionalId']) { + if (type === ACL_RESOURCE_TYPE['Cluster']) { //TODO需要和后端获取集群和事务接口联调 return ( { ); + } else if (type === ACL_RESOURCE_TYPE['TransactionalId']) { + return ; } else if (type === ACL_RESOURCE_TYPE['Topic']) { return ; } else if (type === ACL_RESOURCE_TYPE['Group']) { From af916d5a7162dc5773b2dce16996b9ef438e12dc Mon Sep 17 00:00:00 2001 From: erge Date: Sun, 26 Nov 2023 16:28:29 +0800 Subject: [PATCH 39/48] =?UTF-8?q?[Optimize]Connect-JSON=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E7=9A=84JSON=E6=A0=BC=E5=BC=8F=E5=92=8C=E5=AE=98?= =?UTF-8?q?=E6=96=B9API=E7=9A=84=E6=A0=BC=E5=BC=8F=E4=B8=8D=E4=B8=80?= =?UTF-8?q?=E8=87=B4(#1048)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/Connect/AddConnectorUseJSON.tsx | 88 +++++++++++-------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx index e06ede24e..37d646e9d 100644 --- a/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx +++ b/km-console/packages/layout-clusters-fe/src/pages/Connect/AddConnectorUseJSON.tsx @@ -1,7 +1,7 @@ import api from '@src/api'; import CodeMirrorFormItem from '@src/components/CodeMirrorFormItem'; import customMessage from '@src/components/Message'; -import { Button, Divider, Drawer, Form, message, Space, Utils } from 'knowdesign'; +import { Button, Divider, Drawer, Form, message, Space, Utils, Select } from 'knowdesign'; import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; import { useParams } from 'react-router-dom'; import { ConnectCluster, ConnectorPlugin, ConnectorPluginConfig, OperateInfo } from './AddConnector'; @@ -9,9 +9,8 @@ import { ConnectCluster, ConnectorPlugin, ConnectorPluginConfig, OperateInfo } f const PLACEHOLDER = `配置格式如下 { - "connectClusterName": "", // Connect Cluster 名称 + "name": "", // Connect Cluster 名称 "config": { // 具体配置项 - "name": "", "connector.class": "", "tasks.max": 1, ... @@ -43,11 +42,16 @@ export default forwardRef((props: any, ref) => { const onOpen = (type: 'create' | 'edit', connectClusterName?: string, defaultConfigs?: { [key: string]: any }) => { if (defaultConfigs) { setDefaultConfigs({ ...defaultConfigs, connectClusterName }); + const connectorName = connectClusterName; + const connectClusterId = connectClusters.find((cluster) => cluster.label === connectClusterName).value; form.setFieldsValue({ + connectClusterId, + connectorName, configs: JSON.stringify( { - connectClusterName, - config: defaultConfigs, + // connectClusterName, + name: defaultConfigs.name, + config: { ...defaultConfigs, name: undefined }, }, null, 2 @@ -63,10 +67,11 @@ export default forwardRef((props: any, ref) => { form.validateFields().then( (data) => { const postData = JSON.parse(data.configs); - postData.connectorName = postData.config.name; - postData.connectClusterId = connectClusters.find((cluster) => cluster.label === postData.connectClusterName).value; - delete postData.connectClusterName; - + postData.connectorName = postData.name; + postData.connectClusterId = data.connectClusterId; + postData.config.name = postData.name; + // delete postData.connectClusterName; + delete postData.name; Object.entries(postData.config).forEach(([key, val]) => { if (val === null) { delete postData.config[key]; @@ -161,6 +166,26 @@ export default forwardRef((props: any, ref) => { } >
+ +