diff --git a/admin/admin-ui/src/api/canalInstance.js b/admin/admin-ui/src/api/canalInstance.js index dbb81c7a..2d7f2ac2 100644 --- a/admin/admin-ui/src/api/canalInstance.js +++ b/admin/admin-ui/src/api/canalInstance.js @@ -59,6 +59,13 @@ export function instanceLog(id, nodeId) { }) } +export function instanceMeta(id, nodeId) { + return request({ + url: '/canal/instance/meta/' + id + '/' + nodeId, + method: 'get' + }) +} + export function instanceStatus(id, option) { return request({ url: '/canal/instance/status/' + id + '?option=' + option, diff --git a/admin/admin-ui/src/router/index.js b/admin/admin-ui/src/router/index.js index 269022e7..d1ac3b56 100644 --- a/admin/admin-ui/src/router/index.js +++ b/admin/admin-ui/src/router/index.js @@ -128,6 +128,13 @@ export const constantRoutes = [ component: () => import('@/views/canalServer/CanalInstanceLogDetail'), meta: { title: 'Instance 日志' }, hidden: true + }, + { + path: 'canalInstance/meta', + name: 'Instance meta', + component: () => import('@/views/canalServer/CanalInstanceMetaDetail'), + meta: { title: 'Instance Meta' }, + hidden: true } ] }, diff --git a/admin/admin-ui/src/views/canalServer/CanalInstance.vue b/admin/admin-ui/src/views/canalServer/CanalInstance.vue index 0ec9e56b..918762f4 100644 --- a/admin/admin-ui/src/views/canalServer/CanalInstance.vue +++ b/admin/admin-ui/src/views/canalServer/CanalInstance.vue @@ -64,6 +64,7 @@ 启动 停止 日志 + meta @@ -117,6 +118,7 @@ export default { } }, created() { + this.listQuery.name = this.$route.query.name getClustersAndServers().then((res) => { this.options = res.data }) @@ -222,6 +224,13 @@ export default { return } this.$router.push('canalInstance/log?id=' + row.id + '&nodeId=' + row.nodeServer.id) + }, + handleMeta(row) { + if (row.nodeId === null) { + this.$message({ message: '当前Instance不是启动状态,无法查看meta', type: 'warning' }) + return + } + this.$router.push('canalInstance/meta?id=' + row.id + '&nodeId=' + row.nodeServer.id) } } } diff --git a/admin/admin-ui/src/views/canalServer/CanalInstanceMetaDetail.vue b/admin/admin-ui/src/views/canalServer/CanalInstanceMetaDetail.vue new file mode 100644 index 00000000..19a09aef --- /dev/null +++ b/admin/admin-ui/src/views/canalServer/CanalInstanceMetaDetail.vue @@ -0,0 +1,53 @@ + + + + + + {{ form.instance }}.meta + 刷新 + 返回 + + + + + + + + + + + diff --git a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/AdminConnector.java b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/AdminConnector.java index d06b29cb..1b1368a0 100644 --- a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/AdminConnector.java +++ b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/AdminConnector.java @@ -128,4 +128,12 @@ public interface AdminConnector { */ String instanceLog(String destination, String fileName, int lines); + /** + * meta + * @param destination + * @param fileName + * @return + */ + String instanceMeta(String destination, String fileName); + } diff --git a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java index d3677280..eef3c3e2 100644 --- a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java +++ b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java @@ -206,6 +206,11 @@ public class SimpleAdminConnector implements AdminConnector { return doLogAdmin("instance", "file", destination, fileName, lines); } + @Override + public String instanceMeta(final String destination, final String fileName) { + return doLogAdmin("meta", "file", destination, fileName,100); + } + // ==================== helper method ==================== private String doServerAdmin(String action) { diff --git a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java index e518557b..89e73802 100644 --- a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java +++ b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java @@ -161,6 +161,20 @@ public class CanalInstanceController { return BaseModel.getInstance(canalInstanceConfigService.remoteInstanceLog(id, nodeId)); } + /** + * 获取实例meta信息 + * + * @param id + * @param nodeId + * @param env + * @return + */ + @GetMapping(value = "/instance/meta/{id}/{nodeId}") + public BaseModel> meta(@PathVariable Long id, @PathVariable Long nodeId, + @PathVariable String env) { + return BaseModel.getInstance(canalInstanceConfigService.remoteInstanceMeta(id, nodeId)); + } + /** * 通过Server id获取所有活动的Instance * diff --git a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java index fedd188c..0ed45378 100644 --- a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java +++ b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java @@ -26,6 +26,8 @@ public interface CanalInstanceService { Map remoteInstanceLog(Long id, Long nodeId); + Map remoteInstanceMeta(Long id, Long nodeId); + boolean remoteOperation(Long id, Long nodeId, String option); boolean instanceOperation(Long id, String option); diff --git a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java index 4d1a9d83..5e0408d3 100644 --- a/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java +++ b/admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java @@ -1,8 +1,10 @@ package com.alibaba.otter.canal.admin.service.impl; +import com.alibaba.otter.canal.common.zookeeper.ZkClientx; import io.ebean.Query; import java.security.NoSuchAlgorithmException; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -256,6 +258,33 @@ public class CanalInstanceServiceImpl implements CanalInstanceService { return result; } + @Override + public Map remoteInstanceMeta(final Long id, final Long nodeId) { + Map result = new HashMap<>(); + + NodeServer nodeServer = NodeServer.find.byId(nodeId); + if (nodeServer == null) { + return result; + } + CanalInstanceConfig canalInstanceConfig = CanalInstanceConfig.find.byId(id); + if (canalInstanceConfig == null) { + return result; + } + String meta; + if (nodeServer.getCanalCluster() != null) { + ZkClientx zkClientx = ZkClientx.getZkClient(nodeServer.getCanalCluster().getZkHosts()); + String zkPath = MessageFormat.format("/{0}/{1}/{2}/{3}/{4}/{5}", "otter", "canal", "destinations", canalInstanceConfig.getName(), "1001", "cursor"); + meta = new String((byte[]) zkClientx.readData(zkPath)); + } else { + meta = SimpleAdminConnectors.execute(nodeServer.getIp(), + nodeServer.getAdminPort(), + adminConnector -> adminConnector.instanceMeta(canalInstanceConfig.getName(), "meta.dat")); + } + result.put("instance", canalInstanceConfig.getName()); + result.put("meta", meta); + return result; + } + public boolean remoteOperation(Long id, Long nodeId, String option) { NodeServer nodeServer = null; if ("start".equals(option)) { diff --git a/deployer/src/main/java/com/alibaba/otter/canal/deployer/admin/CanalAdminController.java b/deployer/src/main/java/com/alibaba/otter/canal/deployer/admin/CanalAdminController.java index 5144e7f7..5877f7fe 100644 --- a/deployer/src/main/java/com/alibaba/otter/canal/deployer/admin/CanalAdminController.java +++ b/deployer/src/main/java/com/alibaba/otter/canal/deployer/admin/CanalAdminController.java @@ -218,6 +218,11 @@ public class CanalAdminController implements CanalAdmin { return FileUtils.readFileFromOffset("../logs/" + destination + "/" + fileName, lines, "UTF-8"); } + @Override + public String instanceMeta(String destination, String fileName) { + return FileUtils.readFileFromOffset("../conf/" + destination + "/" + fileName, 100, "UTF-8"); + } + private InstanceAction getInstanceAction(String destination) { Map monitors = canalStater.getController() .getInstanceConfigMonitors(); diff --git a/server/src/main/java/com/alibaba/otter/canal/admin/CanalAdmin.java b/server/src/main/java/com/alibaba/otter/canal/admin/CanalAdmin.java index 9a5ed3fb..69664ac9 100644 --- a/server/src/main/java/com/alibaba/otter/canal/admin/CanalAdmin.java +++ b/server/src/main/java/com/alibaba/otter/canal/admin/CanalAdmin.java @@ -115,4 +115,11 @@ public interface CanalAdmin { * @return 日志信息 */ String instanceLog(String destination, String fileName, int lines); + + /** + * 获取meta + * @param destination + * @return + */ + String instanceMeta(String destination,String fileName); } diff --git a/server/src/main/java/com/alibaba/otter/canal/admin/handler/SessionHandler.java b/server/src/main/java/com/alibaba/otter/canal/admin/handler/SessionHandler.java index ed5abea3..e4d7993b 100644 --- a/server/src/main/java/com/alibaba/otter/canal/admin/handler/SessionHandler.java +++ b/server/src/main/java/com/alibaba/otter/canal/admin/handler/SessionHandler.java @@ -116,6 +116,9 @@ public class SessionHandler extends SimpleChannelHandler { message = canalAdmin.instanceLog(destination, file, count); } break; + case "meta": + message = canalAdmin.instanceMeta(destination, file); + break; default: byte[] errorBytes = AdminNettyUtils.errorPacket(301, MessageFormatter.format("LogAdmin type={} is unknown", type).getMessage());