* admin端口调整完成

* server端适配调整

* 调整部分功能

* 单机/集群admin调试完成

* 重新发布前端页面

* bug fix

* 解决server端admin配置会被远程覆盖的问题
解决default-instance.xml无法加载远程zkServers配置的问题

* 集群模式下取活动实例的问题
This commit is contained in:
rewerma
2019-08-31 12:22:16 +08:00
committed by agapple
parent 89055f7405
commit 274e91f8aa
12 changed files with 135 additions and 68 deletions

View File

@@ -54,6 +54,13 @@ public interface AdminConnector {
*/ */
boolean restart(); boolean restart();
/**
* 获取所有当前节点下所有实例
*
* @return 实例信息
*/
String getInstances();
/** /**
* 获取所有当前节点下运行中的实例 * 获取所有当前节点下运行中的实例
* *

View File

@@ -156,6 +156,11 @@ public class SimpleAdminConnector implements AdminConnector {
return BooleanUtils.toBoolean(Integer.parseInt(doServerAdmin("restart"))); return BooleanUtils.toBoolean(Integer.parseInt(doServerAdmin("restart")));
} }
@Override
public String getInstances() {
return doServerAdmin("instances");
}
@Override @Override
public String getRunningInstances() { public String getRunningInstances() {
return doServerAdmin("list"); return doServerAdmin("list");
@@ -227,11 +232,8 @@ public class SimpleAdminConnector implements AdminConnector {
try { try {
writeWithHeader(Packet.newBuilder() writeWithHeader(Packet.newBuilder()
.setType(PacketType.INSTANCE) .setType(PacketType.INSTANCE)
.setBody(InstanceAdmin.newBuilder() .setBody(
.setDestination(destination) InstanceAdmin.newBuilder().setDestination(destination).setAction(action).build().toByteString())
.setAction(action)
.build()
.toByteString())
.build() .build()
.toByteArray()); .toByteArray());

View File

@@ -162,6 +162,6 @@ public class CanalInstanceController {
*/ */
@GetMapping(value = "/active/instances/{serverId}") @GetMapping(value = "/active/instances/{serverId}")
public BaseModel<List<CanalInstanceConfig>> activeInstances(@PathVariable Long serverId, @PathVariable String env) { public BaseModel<List<CanalInstanceConfig>> activeInstances(@PathVariable Long serverId, @PathVariable String env) {
return BaseModel.getInstance(canalInstanceConfigService.findActiveInstaceByServerId(serverId)); return BaseModel.getInstance(canalInstanceConfigService.findActiveInstanceByServerId(serverId));
} }
} }

View File

@@ -20,8 +20,6 @@ public interface CanalInstanceService {
CanalInstanceConfig detail(Long id); CanalInstanceConfig detail(Long id);
CanalInstanceConfig findOne(String name);
void updateContent(CanalInstanceConfig canalInstanceConfig); void updateContent(CanalInstanceConfig canalInstanceConfig);
void delete(Long id); void delete(Long id);
@@ -32,5 +30,5 @@ public interface CanalInstanceService {
boolean instanceOperation(Long id, String option); boolean instanceOperation(Long id, String option);
List<CanalInstanceConfig> findActiveInstaceByServerId(Long serverId); List<CanalInstanceConfig> findActiveInstanceByServerId(Long serverId);
} }

View File

@@ -3,6 +3,7 @@ package com.alibaba.otter.canal.admin.service.impl;
import java.util.List; import java.util.List;
import com.alibaba.otter.canal.admin.common.exception.ServiceException; import com.alibaba.otter.canal.admin.common.exception.ServiceException;
import com.alibaba.otter.canal.admin.model.CanalInstanceConfig;
import com.alibaba.otter.canal.admin.model.NodeServer; import com.alibaba.otter.canal.admin.model.NodeServer;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -33,6 +34,12 @@ public class CanalClusterServiceImpl implements CanalClusterServic {
throw new ServiceException("Servers exist, delete failed"); throw new ServiceException("Servers exist, delete failed");
} }
// 判断集群下是否存在instance信息
int instanceCnt = CanalInstanceConfig.find.query().where().eq("clusterId", id).findCount();
if (instanceCnt > 0) {
throw new ServiceException("Instances exist, delete failed");
}
CanalCluster canalCluster = CanalCluster.find.byId(id); CanalCluster canalCluster = CanalCluster.find.byId(id);
if (canalCluster != null) { if (canalCluster != null) {
canalCluster.delete(); canalCluster.delete();

View File

@@ -119,13 +119,23 @@ public class CanalInstanceServiceImpl implements CanalInstanceService {
* *
* @param serverId server id * @param serverId server id
*/ */
public List<CanalInstanceConfig> findActiveInstaceByServerId(Long serverId) { public List<CanalInstanceConfig> findActiveInstanceByServerId(Long serverId) {
NodeServer nodeServer = NodeServer.find.byId(serverId); NodeServer nodeServer = NodeServer.find.byId(serverId);
if (nodeServer == null) { if (nodeServer == null) {
return null; return null;
} }
String runningInstances = SimpleAdminConnectors
String runningInstances = null;
if (nodeServer.getClusterId() != null) {// 集群模式
// 只取活动的instances
runningInstances = SimpleAdminConnectors
.execute(nodeServer.getIp(), nodeServer.getAdminPort(), AdminConnector::getRunningInstances); .execute(nodeServer.getIp(), nodeServer.getAdminPort(), AdminConnector::getRunningInstances);
} else {
// 取所属所有instances
runningInstances = SimpleAdminConnectors
.execute(nodeServer.getIp(), nodeServer.getAdminPort(), AdminConnector::getInstances);
}
if (runningInstances == null) { if (runningInstances == null) {
return null; return null;
} }
@@ -227,16 +237,6 @@ public class CanalInstanceServiceImpl implements CanalInstanceService {
} }
} }
@Override
public CanalInstanceConfig findOne(String name) {
CanalInstanceConfig config = CanalInstanceConfig.find.query()
.setDisableLazyLoading(true)
.where()
.eq("name", name)
.findOne();
return config;
}
public Map<String, String> remoteInstanceLog(Long id, Long nodeId) { public Map<String, String> remoteInstanceLog(Long id, Long nodeId) {
Map<String, String> result = new HashMap<>(); Map<String, String> result = new HashMap<>();

View File

@@ -54,6 +54,7 @@ public class CanalController {
private int adminPort; private int adminPort;
// 默认使用spring的方式载入 // 默认使用spring的方式载入
private Map<String, InstanceConfig> instanceConfigs; private Map<String, InstanceConfig> instanceConfigs;
private Map<String, String> runningInstances = new MapMaker().makeMap();
private InstanceConfig globalInstanceConfig; private InstanceConfig globalInstanceConfig;
private Map<String, PlainCanalConfigClient> managerClients; private Map<String, PlainCanalConfigClient> managerClients;
// 监听instance config的变化 // 监听instance config的变化
@@ -169,6 +170,7 @@ public class CanalController {
if (canalMQStarter != null) { if (canalMQStarter != null) {
canalMQStarter.startDestination(destination); canalMQStarter.startDestination(destination);
} }
runningInstances.put(destination, destination);
} finally { } finally {
MDC.remove(CanalConstants.MDC_DESTINATION); MDC.remove(CanalConstants.MDC_DESTINATION);
} }
@@ -181,6 +183,7 @@ public class CanalController {
canalMQStarter.stopDestination(destination); canalMQStarter.stopDestination(destination);
} }
embededCanalServer.stop(destination); embededCanalServer.stop(destination);
runningInstances.remove(destination);
} finally { } finally {
MDC.remove(CanalConstants.MDC_DESTINATION); MDC.remove(CanalConstants.MDC_DESTINATION);
} }
@@ -363,7 +366,7 @@ public class CanalController {
} }
if (config.getMode().isManager()) { if (config.getMode().isManager()) {
PlainCanalInstanceGenerator instanceGenerator = new PlainCanalInstanceGenerator(); PlainCanalInstanceGenerator instanceGenerator = new PlainCanalInstanceGenerator(properties);
instanceGenerator.setCanalConfigClient(managerClients.get(config.getManagerAddress())); instanceGenerator.setCanalConfigClient(managerClients.get(config.getManagerAddress()));
instanceGenerator.setSpringXml(config.getSpringXml()); instanceGenerator.setSpringXml(config.getSpringXml());
return instanceGenerator.generate(destination); return instanceGenerator.generate(destination);
@@ -592,4 +595,7 @@ public class CanalController {
return instanceConfigs; return instanceConfigs;
} }
public Map<String, String> getRunningInstances() {
return runningInstances;
}
} }

View File

@@ -49,19 +49,22 @@ public class CanalLauncher {
if (StringUtils.isNotEmpty(managerAddress)) { if (StringUtils.isNotEmpty(managerAddress)) {
String user = properties.getProperty(CanalConstants.CANAL_ADMIN_USER); String user = properties.getProperty(CanalConstants.CANAL_ADMIN_USER);
String passwd = properties.getProperty(CanalConstants.CANAL_ADMIN_PASSWD); String passwd = properties.getProperty(CanalConstants.CANAL_ADMIN_PASSWD);
String adminPort = properties.getProperty(CanalConstants.CANAL_ADMIN_PORT); String adminPort = properties.getProperty(CanalConstants.CANAL_ADMIN_PORT, "11110");
if (StringUtils.isEmpty(adminPort)) {
adminPort = "11110";
}
final PlainCanalConfigClient configClient = new PlainCanalConfigClient(managerAddress, final PlainCanalConfigClient configClient = new PlainCanalConfigClient(managerAddress,
user, user,
passwd, passwd,
"", "",
Integer.parseInt(adminPort)); Integer.parseInt(adminPort));
PlainCanal canalConfig = configClient.findServer(null); PlainCanal canalConfig = configClient.findServer(null);
if (canalConfig != null) {
properties = canalConfig.getProperties(); properties = canalConfig.getProperties();
// 用本地配置覆盖
properties.put(CanalConstants.CANAL_ADMIN_MANAGER, managerAddress);
properties.put(CanalConstants.CANAL_ADMIN_USER, user);
properties.put(CanalConstants.CANAL_ADMIN_PASSWD, passwd);
properties.put(CanalConstants.CANAL_ADMIN_PORT, adminPort);
int scanIntervalInSecond = Integer int scanIntervalInSecond = Integer
.valueOf(properties.getProperty(CanalConstants.CANAL_AUTO_SCAN_INTERVAL, "5")); .parseInt(properties.getProperty(CanalConstants.CANAL_AUTO_SCAN_INTERVAL, "5"));
executor.scheduleWithFixedDelay(new Runnable() { executor.scheduleWithFixedDelay(new Runnable() {
private PlainCanal lastCanalConfig; private PlainCanal lastCanalConfig;
@@ -75,7 +78,13 @@ public class CanalLauncher {
if (newCanalConfig != null) { if (newCanalConfig != null) {
// 远程配置canal.properties修改重新加载整个应用 // 远程配置canal.properties修改重新加载整个应用
canalStater.stop(); canalStater.stop();
canalStater.setProperties(newCanalConfig.getProperties()); Properties properties1 = newCanalConfig.getProperties();
// 用本地配置覆盖
properties1.put(CanalConstants.CANAL_ADMIN_MANAGER, managerAddress);
properties1.put(CanalConstants.CANAL_ADMIN_USER, user);
properties1.put(CanalConstants.CANAL_ADMIN_PASSWD, passwd);
properties1.put(CanalConstants.CANAL_ADMIN_PORT, adminPort);
canalStater.setProperties(properties1);
canalStater.start(); canalStater.start();
lastCanalConfig = newCanalConfig; lastCanalConfig = newCanalConfig;
@@ -89,6 +98,7 @@ public class CanalLauncher {
}, 0, scanIntervalInSecond, TimeUnit.SECONDS); }, 0, scanIntervalInSecond, TimeUnit.SECONDS);
} }
}
canalStater.setProperties(properties); canalStater.setProperties(properties);
canalStater.start(); canalStater.start();
@@ -108,5 +118,4 @@ public class CanalLauncher {
} }
}); });
} }
} }

View File

@@ -103,7 +103,7 @@ public class CanalAdminController implements CanalAdmin {
} }
@Override @Override
public String getRunningInstances() { public String getInstances() {
try { try {
CanalController controller = canalStater.getController(); CanalController controller = canalStater.getController();
if (controller != null) { if (controller != null) {
@@ -118,6 +118,22 @@ public class CanalAdminController implements CanalAdmin {
return ""; return "";
} }
@Override
public String getRunningInstances() {
try {
CanalController controller = canalStater.getController();
if (controller != null) {
Map<String, String> instanceConfigs = controller.getRunningInstances();
if (instanceConfigs != null) {
return Joiner.on(",").join(instanceConfigs.keySet());
}
}
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
return "";
}
@Override @Override
public boolean checkInstance(String destination) { public boolean checkInstance(String destination) {
Map<String, CanalInstance> instances = CanalServerWithEmbedded.instance().getCanalInstances(); Map<String, CanalInstance> instances = CanalServerWithEmbedded.instance().getCanalInstances();

View File

@@ -13,6 +13,8 @@ import com.alibaba.otter.canal.instance.manager.plain.PlainCanal;
import com.alibaba.otter.canal.instance.manager.plain.PlainCanalConfigClient; import com.alibaba.otter.canal.instance.manager.plain.PlainCanalConfigClient;
import com.alibaba.otter.canal.instance.spring.SpringCanalInstanceGenerator; import com.alibaba.otter.canal.instance.spring.SpringCanalInstanceGenerator;
import java.util.Properties;
/** /**
* 基于manager生成对应的{@linkplain CanalInstance} * 基于manager生成对应的{@linkplain CanalInstance}
* *
@@ -26,6 +28,11 @@ public class PlainCanalInstanceGenerator implements CanalInstanceGenerator {
private PlainCanalConfigClient canalConfigClient; private PlainCanalConfigClient canalConfigClient;
private String defaultName = "instance"; private String defaultName = "instance";
private BeanFactory beanFactory; private BeanFactory beanFactory;
private Properties canalConfig;
public PlainCanalInstanceGenerator(Properties canalConfig){
this.canalConfig = canalConfig;
}
public CanalInstance generate(String destination) { public CanalInstance generate(String destination) {
synchronized (CanalInstanceGenerator.class) { synchronized (CanalInstanceGenerator.class) {
@@ -34,8 +41,11 @@ public class PlainCanalInstanceGenerator implements CanalInstanceGenerator {
if (canal == null) { if (canal == null) {
throw new CanalException("instance : " + destination + " config is not found"); throw new CanalException("instance : " + destination + " config is not found");
} }
Properties properties = canal.getProperties();
properties.putAll(canalConfig);
// 设置动态properties,替换掉本地properties // 设置动态properties,替换掉本地properties
com.alibaba.otter.canal.instance.spring.support.PropertyPlaceholderConfigurer.propertiesLocal.set(canal.getProperties()); com.alibaba.otter.canal.instance.spring.support.PropertyPlaceholderConfigurer.propertiesLocal
.set(properties);
// 设置当前正在加载的通道,加载spring查找文件时会用到该变量 // 设置当前正在加载的通道,加载spring查找文件时会用到该变量
System.setProperty("canal.instance.destination", destination); System.setProperty("canal.instance.destination", destination);
this.beanFactory = getBeanFactory(springXml); this.beanFactory = getBeanFactory(springXml);

View File

@@ -41,6 +41,13 @@ public interface CanalAdmin {
*/ */
boolean restart(); boolean restart();
/**
* 获取所有当前节点下所有实例
*
* @return 实例信息
*/
String getInstances();
/** /**
* 获取所有当前节点下运行中的实例 * 获取所有当前节点下运行中的实例
* *

View File

@@ -58,6 +58,9 @@ public class SessionHandler extends SimpleChannelHandler {
case "list": case "list":
message = canalAdmin.getRunningInstances(); message = canalAdmin.getRunningInstances();
break; break;
case "instances":
message = canalAdmin.getInstances();
break;
default: default:
byte[] errorBytes = AdminNettyUtils.errorPacket(301, byte[] errorBytes = AdminNettyUtils.errorPacket(301,
MessageFormatter.format("ServerAdmin action={} is unknown", action).getMessage()); MessageFormatter.format("ServerAdmin action={} is unknown", action).getMessage());
@@ -129,9 +132,11 @@ public class SessionHandler extends SimpleChannelHandler {
} }
} catch (Throwable exception) { } catch (Throwable exception) {
byte[] errorBytes = AdminNettyUtils.errorPacket(400, byte[] errorBytes = AdminNettyUtils.errorPacket(400,
MessageFormatter.format("something goes wrong with channel:{}, exception={}", MessageFormatter
.format("something goes wrong with channel:{}, exception={}",
ctx.getChannel(), ctx.getChannel(),
ExceptionUtils.getStackTrace(exception)).getMessage()); ExceptionUtils.getStackTrace(exception))
.getMessage());
AdminNettyUtils.write(ctx.getChannel(), errorBytes); AdminNettyUtils.write(ctx.getChannel(), errorBytes);
} }
} }