mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
@@ -18,9 +18,4 @@ public class CanalAdminApplication {
|
||||
application.setBannerMode(Banner.Mode.OFF);
|
||||
application.run(args);
|
||||
}
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// UserAgent userAgent = new UserAgent();
|
||||
//// HelloAgent helloAgent = new HelloAgent
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -13,6 +13,12 @@ import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.UnderscoreNamingConvention;
|
||||
|
||||
/**
|
||||
* Ebean 配置
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
public class EbeanConfig {
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@ import com.alibaba.otter.canal.admin.model.BaseModel;
|
||||
import com.alibaba.otter.canal.admin.model.User;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* 相关MVC拦截器配置
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@ import org.springframework.web.bind.annotation.*;
|
||||
import com.alibaba.otter.canal.admin.model.CanalConfig;
|
||||
import com.alibaba.otter.canal.admin.service.CanalConfigService;
|
||||
|
||||
/**
|
||||
* Canal主配置管理控制层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/{env}/canal")
|
||||
public class CanalConfigController {
|
||||
@@ -14,11 +20,24 @@ public class CanalConfigController {
|
||||
@Autowired
|
||||
CanalConfigService canalConfigService;
|
||||
|
||||
/**
|
||||
* 获取配置信息
|
||||
*
|
||||
* @param env 环境变量
|
||||
* @return 配置信息
|
||||
*/
|
||||
@GetMapping(value = "/config")
|
||||
public BaseModel<CanalConfig> canalConfig(@PathVariable String env) {
|
||||
return BaseModel.getInstance(canalConfigService.getCanalConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改配置
|
||||
*
|
||||
* @param canalConfig 配置信息对象
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/config")
|
||||
public BaseModel<String> updateConfig(@RequestBody CanalConfig canalConfig, @PathVariable String env) {
|
||||
canalConfigService.updateContent(canalConfig);
|
||||
|
||||
@@ -10,6 +10,12 @@ import com.alibaba.otter.canal.admin.model.BaseModel;
|
||||
import com.alibaba.otter.canal.admin.model.CanalInstanceConfig;
|
||||
import com.alibaba.otter.canal.admin.service.CanalInstanceService;
|
||||
|
||||
/**
|
||||
* Canal Instance配置管理控制层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/{env}/canal")
|
||||
public class CanalInstanceController {
|
||||
@@ -17,45 +23,103 @@ public class CanalInstanceController {
|
||||
@Autowired
|
||||
CanalInstanceService canalInstanceConfigService;
|
||||
|
||||
/**
|
||||
* 实例配置列表
|
||||
*
|
||||
* @param canalInstanceConfig 查询对象
|
||||
* @param env 环境变量
|
||||
* @return 实例列表
|
||||
*/
|
||||
@GetMapping(value = "/instances")
|
||||
public BaseModel<List<CanalInstanceConfig>> nodeServers(CanalInstanceConfig canalInstanceConfig,
|
||||
@PathVariable String env) {
|
||||
return BaseModel.getInstance(canalInstanceConfigService.findList(canalInstanceConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存实例配置
|
||||
*
|
||||
* @param canalInstanceConfig 实例配置对象
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PostMapping(value = "/instance")
|
||||
public BaseModel<String> save(@RequestBody CanalInstanceConfig canalInstanceConfig, @PathVariable String env) {
|
||||
canalInstanceConfigService.save(canalInstanceConfig);
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例详情信息
|
||||
*
|
||||
* @param id 实例配置id
|
||||
* @param env 环境变量
|
||||
* @return 实例信息
|
||||
*/
|
||||
@GetMapping(value = "/instance/{id}")
|
||||
public BaseModel<CanalInstanceConfig> detail(@PathVariable Long id, @PathVariable String env) {
|
||||
return BaseModel.getInstance(canalInstanceConfigService.detail(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改实例配置
|
||||
*
|
||||
* @param canalInstanceConfig 实例配置信息
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/instance")
|
||||
public BaseModel<String> update(@RequestBody CanalInstanceConfig canalInstanceConfig, @PathVariable String env) {
|
||||
canalInstanceConfigService.updateContent(canalInstanceConfig);
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除实例配置
|
||||
*
|
||||
* @param id 实例配置id
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@DeleteMapping(value = "/instance/{id}")
|
||||
public BaseModel<String> delete(@PathVariable Long id, @PathVariable String env) {
|
||||
canalInstanceConfigService.delete(id);
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动远程实例
|
||||
*
|
||||
* @param id 实例配置id
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/instance/start/{id}")
|
||||
public BaseModel<Boolean> start(@PathVariable Long id, @PathVariable String env) {
|
||||
return BaseModel.getInstance(canalInstanceConfigService.remoteOperation(id, null, "start"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭远程实例
|
||||
*
|
||||
* @param id 实例配置id
|
||||
* @param nodeId 节点id
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/instance/stop/{id}/{nodeId}")
|
||||
public BaseModel<Boolean> stop(@PathVariable Long id, @PathVariable Long nodeId, @PathVariable String env) {
|
||||
return BaseModel.getInstance(canalInstanceConfigService.remoteOperation(id, nodeId, "stop"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取远程实例运行日志
|
||||
*
|
||||
* @param id 实例配置id
|
||||
* @param nodeId 节点id
|
||||
* @param env 环境变量
|
||||
* @return 实例日志信息
|
||||
*/
|
||||
@GetMapping(value = "/instance/log/{id}/{nodeId}")
|
||||
public BaseModel<Map<String, String>> start(@PathVariable Long id, @PathVariable Long nodeId,
|
||||
@PathVariable String env) {
|
||||
|
||||
@@ -9,6 +9,12 @@ import com.alibaba.otter.canal.admin.model.BaseModel;
|
||||
import com.alibaba.otter.canal.admin.model.NodeServer;
|
||||
import com.alibaba.otter.canal.admin.service.NodeServerService;
|
||||
|
||||
/**
|
||||
* 节点信息控制层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/{env}")
|
||||
public class NodeServerController {
|
||||
@@ -16,49 +22,113 @@ public class NodeServerController {
|
||||
@Autowired
|
||||
NodeServerService nodeServerService;
|
||||
|
||||
/**
|
||||
* 获取所有节点信息列表
|
||||
*
|
||||
* @param nodeServer 筛选条件
|
||||
* @param env 环境变量
|
||||
* @return 节点信息列表
|
||||
*/
|
||||
@GetMapping(value = "/nodeServers")
|
||||
public BaseModel<List<NodeServer>> nodeServers(NodeServer nodeServer, @PathVariable String env) {
|
||||
return BaseModel.getInstance(nodeServerService.findList(nodeServer));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存节点信息
|
||||
*
|
||||
* @param nodeServer 节点信息
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PostMapping(value = "/nodeServer")
|
||||
public BaseModel<String> save(@RequestBody NodeServer nodeServer, @PathVariable String env) {
|
||||
nodeServerService.save(nodeServer);
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点信息详情
|
||||
*
|
||||
* @param id 节点信息id
|
||||
* @param env 环境变量
|
||||
* @return 检点信息
|
||||
*/
|
||||
@GetMapping(value = "/nodeServer/{id}")
|
||||
public BaseModel<NodeServer> detail(@PathVariable Long id, @PathVariable String env) {
|
||||
return BaseModel.getInstance(nodeServerService.detail(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改节点信息
|
||||
*
|
||||
* @param nodeServer 节点信息
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/nodeServer")
|
||||
public BaseModel<String> update(@RequestBody NodeServer nodeServer, @PathVariable String env) {
|
||||
nodeServerService.update(nodeServer);
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除节点信息
|
||||
*
|
||||
* @param id 节点信息id
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@DeleteMapping(value = "/nodeServer/{id}")
|
||||
public BaseModel<String> delete(@PathVariable Long id, @PathVariable String env) {
|
||||
nodeServerService.delete(id);
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取远程节点运行状态
|
||||
*
|
||||
* @param ip 节点ip
|
||||
* @param port 节点端口
|
||||
* @param env 环境变量
|
||||
* @return 状态信息
|
||||
*/
|
||||
@GetMapping(value = "/nodeServer/status")
|
||||
public BaseModel<Integer> status(@RequestParam String ip, @RequestParam Integer port, @PathVariable String env) {
|
||||
return BaseModel.getInstance(nodeServerService.remoteNodeStatus(ip, port));
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动远程节点
|
||||
*
|
||||
* @param id 节点id
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/nodeServer/start/{id}")
|
||||
public BaseModel<Boolean> start(@PathVariable Long id, @PathVariable String env) {
|
||||
return BaseModel.getInstance(nodeServerService.remoteOperation(id, "start"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取远程节点日志
|
||||
*
|
||||
* @param id 节点id
|
||||
* @param env 环境变量
|
||||
* @return 节点日志
|
||||
*/
|
||||
@GetMapping(value = "/nodeServer/log/{id}")
|
||||
public BaseModel<String> log(@PathVariable Long id, @PathVariable String env) {
|
||||
return BaseModel.getInstance(nodeServerService.remoteCanalLog(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭远程节点
|
||||
*
|
||||
* @param id 节点id
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "/nodeServer/stop/{id}")
|
||||
public BaseModel<Boolean> stop(@PathVariable Long id, @PathVariable String env) {
|
||||
return BaseModel.getInstance(nodeServerService.remoteOperation(id, "stop"));
|
||||
|
||||
@@ -15,6 +15,12 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 用户管理控制层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/{env}/user")
|
||||
public class UserController {
|
||||
@@ -22,11 +28,18 @@ public class UserController {
|
||||
public static final LoadingCache<String, User> loginUsers = Caffeine.newBuilder()
|
||||
.maximumSize(10_000)
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build(key -> null);
|
||||
.build(key -> null); // 用户登录信息缓存
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param user 账号密码
|
||||
* @param env 环境变量
|
||||
* @return token
|
||||
*/
|
||||
@PostMapping(value = "/login")
|
||||
public BaseModel<Map<String, String>> login(@RequestBody User user, @PathVariable String env) {
|
||||
User loginUser = userService.find4Login(user.getUsername(), user.getPassword());
|
||||
@@ -44,6 +57,13 @@ public class UserController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param token token
|
||||
* @param env 环境变量
|
||||
* @return 用户信息
|
||||
*/
|
||||
@GetMapping(value = "/info")
|
||||
public BaseModel<User> info(@RequestParam String token, @PathVariable String env) {
|
||||
User user = loginUsers.getIfPresent(token);
|
||||
@@ -57,6 +77,14 @@ public class UserController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param env 环境变量
|
||||
* @param httpServletRequest httpServletRequest
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PutMapping(value = "")
|
||||
public BaseModel<String> update(@RequestBody User user, @PathVariable String env,
|
||||
HttpServletRequest httpServletRequest) {
|
||||
@@ -66,6 +94,12 @@ public class UserController {
|
||||
return BaseModel.getInstance("success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户退出
|
||||
*
|
||||
* @param env 环境变量
|
||||
* @return 是否成功
|
||||
*/
|
||||
@PostMapping(value = "/logout")
|
||||
public BaseModel<String> logout(@PathVariable String env) {
|
||||
return BaseModel.getInstance("success");
|
||||
|
||||
@@ -10,11 +10,23 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* MVC异常拦截器
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@ControllerAdvice(annotations = ResponseBody.class)
|
||||
public class CustomExceptionHandler {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* 通用异常处理
|
||||
*
|
||||
* @param e 异常
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
|
||||
@@ -1,26 +1,90 @@
|
||||
package com.alibaba.otter.canal.admin.jmx;
|
||||
|
||||
/**
|
||||
* Canal Server JMX MBean
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public interface CanalServerMXBean {
|
||||
|
||||
/**
|
||||
* 获取Canal Server状态
|
||||
*
|
||||
* @return 状态代码
|
||||
*/
|
||||
int getStatus();
|
||||
|
||||
/**
|
||||
* 启动Canal Server
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean start();
|
||||
|
||||
/**
|
||||
* 停止Canal Server
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean stop();
|
||||
|
||||
/**
|
||||
* 重启Canal Server
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean restart();
|
||||
|
||||
/**
|
||||
* 退出Canal Server(关闭进程)
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean exit();
|
||||
|
||||
/**
|
||||
* 通过实例名启动实例
|
||||
*
|
||||
* @param destination 实例名
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean startInstance(String destination);
|
||||
|
||||
/**
|
||||
* 通过实例名关闭实例
|
||||
*
|
||||
* @param destination 实例名
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean stopInstance(String destination);
|
||||
|
||||
/**
|
||||
* 通过实例名重启实例
|
||||
*
|
||||
* @param destination 实例名
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean reloadInstance(String destination);
|
||||
|
||||
/**
|
||||
* 获取所有当前节点下运行中的实例
|
||||
*
|
||||
* @return 实例信息
|
||||
*/
|
||||
String getRunningInstances();
|
||||
|
||||
/**
|
||||
* 获取Canal Server日志(末尾100行)
|
||||
*
|
||||
* @return 日志信息
|
||||
*/
|
||||
String canalLog();
|
||||
|
||||
/**
|
||||
* 通过实例名获取实例日志(末尾100行)
|
||||
*
|
||||
* @return 日志信息
|
||||
*/
|
||||
String instanceLog(String destination);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Canal Server JMX 控制层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class JMXConnection {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JMXConnection.class);
|
||||
@@ -28,6 +34,15 @@ public class JMXConnection {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行相关操作
|
||||
*
|
||||
* @param ip jmx ip
|
||||
* @param port jmx port
|
||||
* @param function 执行方法
|
||||
* @param <R> 返回泛型
|
||||
* @return 执行结果
|
||||
*/
|
||||
public static <R> R execute(String ip, int port, Function<CanalServerMXBean, R> function) {
|
||||
JMXConnection jmxConnection = new JMXConnection(ip, port);
|
||||
try {
|
||||
@@ -41,6 +56,9 @@ public class JMXConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接远程jmx
|
||||
*/
|
||||
public void connect() {
|
||||
try {
|
||||
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi");
|
||||
@@ -57,6 +75,15 @@ public class JMXConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 带超时的jmx连接器
|
||||
*
|
||||
* @param url jmx url
|
||||
* @param timeout 超时时间
|
||||
* @param unit 超时时间单位
|
||||
* @return JMXConnector
|
||||
* @throws IOException 连接异常
|
||||
*/
|
||||
private static JMXConnector connectWithTimeout(final JMXServiceURL url, long timeout,
|
||||
TimeUnit unit) throws IOException {
|
||||
final BlockingQueue<Object> mailbox = new ArrayBlockingQueue<>(1);
|
||||
@@ -108,6 +135,11 @@ public class JMXConnection {
|
||||
|
||||
private static final ThreadFactory daemonThreadFactory = new DaemonThreadFactory();
|
||||
|
||||
/**
|
||||
* 获取MBean
|
||||
*
|
||||
* @return canalServerMXBean
|
||||
*/
|
||||
public CanalServerMXBean getCanalServerMXBean() {
|
||||
if (jmxc == null) {
|
||||
connect();
|
||||
@@ -115,6 +147,9 @@ public class JMXConnection {
|
||||
return canalServerMXBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭jmx连接
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
if (jmxc != null) {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package com.alibaba.otter.canal.admin.model;
|
||||
|
||||
/**
|
||||
* 基础Model
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class BaseModel<T> {
|
||||
|
||||
private Integer code = 20000;
|
||||
|
||||
@@ -7,6 +7,12 @@ import java.util.Date;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* Canal住配置实体类
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Entity
|
||||
public class CanalConfig extends Model {
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@ import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Canal实例配置信息实体类
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Entity
|
||||
public class CanalInstanceConfig extends Model {
|
||||
|
||||
@@ -30,7 +36,7 @@ public class CanalInstanceConfig extends Model {
|
||||
private Date modifiedTime;
|
||||
|
||||
@Transient
|
||||
private Long nodeId;
|
||||
private Long nodeId;
|
||||
@Transient
|
||||
private String nodeIp;
|
||||
|
||||
|
||||
@@ -9,6 +9,12 @@ import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* EBean Model扩展类
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class Model extends io.ebean.Model {
|
||||
|
||||
|
||||
@@ -8,6 +8,12 @@ import javax.persistence.Table;
|
||||
|
||||
import io.ebean.Finder;
|
||||
|
||||
/**
|
||||
* 节点信息实体类
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "canal_node_server")
|
||||
public class NodeServer extends Model {
|
||||
|
||||
@@ -8,9 +8,12 @@ import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户信息实体类
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "canal_user")
|
||||
public class User extends Model{
|
||||
public class User extends Model {
|
||||
|
||||
public static final UserFinder find = new UserFinder();
|
||||
|
||||
|
||||
@@ -5,6 +5,12 @@ import com.alibaba.otter.canal.admin.model.CanalInstanceConfig;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Canal实例配置信息业务层接口
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public interface CanalInstanceService {
|
||||
|
||||
List<CanalInstanceConfig> findList(CanalInstanceConfig canalInstanceConfig);
|
||||
|
||||
@@ -5,6 +5,12 @@ import org.springframework.stereotype.Service;
|
||||
import com.alibaba.otter.canal.admin.model.CanalConfig;
|
||||
import com.alibaba.otter.canal.admin.service.CanalConfigService;
|
||||
|
||||
/**
|
||||
* Canal配置信息业务层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class CanalConfigServiceImpl implements CanalConfigService {
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@ import com.alibaba.otter.canal.admin.service.CanalInstanceService;
|
||||
|
||||
import io.ebean.Query;
|
||||
|
||||
/**
|
||||
* Canal实例配置信息业务层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class CanalInstanceServiceImpl implements CanalInstanceService {
|
||||
|
||||
|
||||
@@ -20,6 +20,12 @@ import com.alibaba.otter.canal.admin.service.NodeServerService;
|
||||
|
||||
import io.ebean.Query;
|
||||
|
||||
/**
|
||||
* 节点信息业务层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class NodeServerServiceImpl implements NodeServerService {
|
||||
|
||||
|
||||
@@ -6,6 +6,12 @@ import com.alibaba.otter.canal.admin.service.UserService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 用户信息业务层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.alibaba.otter.canal.admin;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { CanalAdminApplication.class })
|
||||
|
||||
public class BaseTest {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.alibaba.otter.canal.admin;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class TestApplication {
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.alibaba.otter.canal.admin.service;
|
||||
|
||||
import com.alibaba.otter.canal.admin.BaseTest;
|
||||
import com.alibaba.otter.canal.admin.model.NodeServer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NodeServerServiceTest extends BaseTest {
|
||||
|
||||
@Autowired
|
||||
NodeServerService nodeServerService;
|
||||
|
||||
@Test
|
||||
public void findList() {
|
||||
List<NodeServer> list = nodeServerService.findList(null);
|
||||
Assert.assertNotNull(list);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
spring.datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/canal_manager?useUnicode=true&characterEncoding=UTF-8&useSSL=false
|
||||
username: root
|
||||
password: 121212
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
hikari:
|
||||
maximum-pool-size: 10
|
||||
minimum-idle: 1
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.alibaba.otter.canal.admin: DEBUG
|
||||
@@ -16,6 +16,12 @@ import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
/**
|
||||
* Canal Server Agent 用于远程JMX调用
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class CanalServerAgent implements NotificationListener {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CanalServerBean.class);
|
||||
|
||||
@@ -14,6 +14,12 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.management.NotificationBroadcasterSupport;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Canal配置信息业务层
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class CanalServerBean extends NotificationBroadcasterSupport implements CanalServerMXBean {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CanalServerBean.class);
|
||||
|
||||
@@ -1,26 +1,90 @@
|
||||
package com.alibaba.otter.canal.deployer.mbean;
|
||||
|
||||
/**
|
||||
* Canal Server JMX MBean
|
||||
*
|
||||
* @author rewerma 2019-07-13 下午05:12:16
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public interface CanalServerMXBean {
|
||||
|
||||
/**
|
||||
* 获取Canal Server状态
|
||||
*
|
||||
* @return 状态代码
|
||||
*/
|
||||
int getStatus();
|
||||
|
||||
/**
|
||||
* 启动Canal Server
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean start();
|
||||
|
||||
/**
|
||||
* 停止Canal Server
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean stop();
|
||||
|
||||
/**
|
||||
* 重启Canal Server
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean restart();
|
||||
|
||||
/**
|
||||
* 退出Canal Server(关闭进程)
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean exit();
|
||||
|
||||
/**
|
||||
* 通过实例名启动实例
|
||||
*
|
||||
* @param destination 实例名
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean startInstance(String destination);
|
||||
|
||||
/**
|
||||
* 通过实例名关闭实例
|
||||
*
|
||||
* @param destination 实例名
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean stopInstance(String destination);
|
||||
|
||||
/**
|
||||
* 通过实例名重启实例
|
||||
*
|
||||
* @param destination 实例名
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean reloadInstance(String destination);
|
||||
|
||||
/**
|
||||
* 获取所有当前节点下运行中的实例
|
||||
*
|
||||
* @return 实例信息
|
||||
*/
|
||||
String getRunningInstances();
|
||||
|
||||
/**
|
||||
* 获取Canal Server日志(末尾100行)
|
||||
*
|
||||
* @return 日志信息
|
||||
*/
|
||||
String canalLog();
|
||||
|
||||
/**
|
||||
* 通过实例名获取实例日志(末尾100行)
|
||||
*
|
||||
* @return 日志信息
|
||||
*/
|
||||
String instanceLog(String destination);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user