赞
踩
在前面的统计分析功能中,我们采取了服务调用获取统计数据,这样耦合度高,效率相对较低,目前我采取另一种实现方式,通过实时同步数据库表的方式实现,例如我们要统计每天注册与登录人数,我们只需把会员表同步到统计库中,实现本地统计就可以了,这样效率更高,耦合度更低,Canal就是一个很好的数据库同步工具。canal是阿里巴巴旗下的一款开源项目,纯Java开发。基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL。
创建的备份数据库与表,要与被同步数据的数据库结构一致。
这里,我在腾讯云服务器和本地都创建了一个测试库。
canal的原理是基于mysql binlog技术,所以这里一定需要开启mysql的binlog写入功能。
show variables like 'log_bin'
vi /etc/my.cnf
追加内容:
log-bin=mysql-bin #binlog文件名
binlog_format=ROW #选择row模式
server_id=1 #mysql实例id,不能和canal的slaveId重复
service mysql restart
如果出现:
则使用:systemctl restart mysqld.service
CREATE USER 'canal'@'%' IDENTIFIED BY '自己密码';
GRANT SHOW VIEW, SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;
/usr/local/canal
tar zxvf canal.deployer-1.1.4.tar.gz
vi conf/example/instance.properties
#需要改成自己的数据库信息
canal.instance.master.address=192.168.44.132:3306
#需要改成自己的数据库用户名与密码
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
#需要改成同步的数据库表规则,例如只是同步一下表
#canal.instance.filter.regex=.*\\..*
canal.instance.filter.regex=guli_ucenter.ucenter_member
进入bin目录,启动
./startup.sh
canal_client
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.alibaba.otter</groupId> <artifactId>canal.client</artifactId> </dependency> </dependencies>
package com.scbg.canal.client; import com.alibaba.otter.canal.client.CanalConnector; import com.alibaba.otter.canal.client.CanalConnectors; import com.alibaba.otter.canal.protocol.CanalEntry.*; import com.alibaba.otter.canal.protocol.Message; import com.google.protobuf.InvalidProtocolBufferException; import org.apache.commons.dbutils.DbUtils; import org.apache.commons.dbutils.QueryRunner; import org.springframework.stereotype.Component; import javax.annotation.Resource; import javax.sql.DataSource; import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.SQLException; import java.util.Iterator; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * @program: education * @description: * @author: WL * @create: 2020-07-10 11:11 **/ @Component public class CanalClient { //sql队列 private Queue<String> SQL_QUEUE = new ConcurrentLinkedQueue<>(); @Resource private DataSource dataSource; /** * canal入库方法 */ public void run() { CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("192.168.44.132", 11111), "example", "", ""); int batchSize = 1000; try { connector.connect(); connector.subscribe(".*\\..*"); connector.rollback(); try { while (true) { //尝试从master那边拉去数据batchSize条记录,有多少取多少 Message message = connector.getWithoutAck(batchSize); long batchId = message.getId(); int size = message.getEntries().size(); if (batchId == -1 || size == 0) { Thread.sleep(1000); } else { dataHandle(message.getEntries()); } connector.ack(batchId); //当队列里面堆积的sql大于一定数值的时候就模拟执行 if (SQL_QUEUE.size() >= 1) { executeQueueSql(); } } } catch (InterruptedException e) { e.printStackTrace(); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } finally { connector.disconnect(); } } /** * 模拟执行队列里面的sql语句 */ public void executeQueueSql() { int size = SQL_QUEUE.size(); for (int i = 0; i < size; i++) { String sql = SQL_QUEUE.poll(); System.out.println("[sql]----> " + sql); this.execute(sql.toString()); } } /** * 数据处理 * * @param entrys */ private void dataHandle(List<Entry> entrys) throws InvalidProtocolBufferException { for (Entry entry : entrys) { if (EntryType.ROWDATA == entry.getEntryType()) { RowChange rowChange = RowChange.parseFrom(entry.getStoreValue()); EventType eventType = rowChange.getEventType(); if (eventType == EventType.DELETE) { saveDeleteSql(entry); } else if (eventType == EventType.UPDATE) { saveUpdateSql(entry); } else if (eventType == EventType.INSERT) { saveInsertSql(entry); } } } } /** * 保存更新语句 * * @param entry */ private void saveUpdateSql(Entry entry) { try { RowChange rowChange = RowChange.parseFrom(entry.getStoreValue()); List<RowData> rowDatasList = rowChange.getRowDatasList(); for (RowData rowData : rowDatasList) { List<Column> newColumnList = rowData.getAfterColumnsList(); StringBuffer sql = new StringBuffer("update " + entry.getHeader().getTableName() + " set "); for (int i = 0; i < newColumnList.size(); i++) { sql.append(" " + newColumnList.get(i).getName() + " = '" + newColumnList.get(i).getValue() + "'"); if (i != newColumnList.size() - 1) { sql.append(","); } } sql.append(" where "); List<Column> oldColumnList = rowData.getBeforeColumnsList(); for (Column column : oldColumnList) { if (column.getIsKey()) { //暂时只支持单一主键 sql.append(column.getName() + "=" + column.getValue()); break; } } SQL_QUEUE.add(sql.toString()); } } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } /** * 保存删除语句 * * @param entry */ private void saveDeleteSql(Entry entry) { try { RowChange rowChange = RowChange.parseFrom(entry.getStoreValue()); List<RowData> rowDatasList = rowChange.getRowDatasList(); for (RowData rowData : rowDatasList) { List<Column> columnList = rowData.getBeforeColumnsList(); StringBuffer sql = new StringBuffer("delete from " + entry.getHeader().getTableName() + " where "); for (Column column : columnList) { if (column.getIsKey()) { //暂时只支持单一主键 sql.append(column.getName() + "=" + column.getValue()); break; } } SQL_QUEUE.add(sql.toString()); } } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } /** * 保存插入语句 * * @param entry */ private void saveInsertSql(Entry entry) { try { RowChange rowChange = RowChange.parseFrom(entry.getStoreValue()); List<RowData> rowDatasList = rowChange.getRowDatasList(); for (RowData rowData : rowDatasList) { List<Column> columnList = rowData.getAfterColumnsList(); StringBuffer sql = new StringBuffer("insert into " + entry.getHeader().getTableName() + " ("); for (int i = 0; i < columnList.size(); i++) { sql.append(columnList.get(i).getName()); if (i != columnList.size() - 1) { sql.append(","); } } sql.append(") VALUES ("); for (int i = 0; i < columnList.size(); i++) { sql.append("'" + columnList.get(i).getValue() + "'"); if (i != columnList.size() - 1) { sql.append(","); } } sql.append(")"); SQL_QUEUE.add(sql.toString()); } } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } /** * 入库 * @param sql */ public void execute(String sql) { Connection con = null; try { if(null == sql) return; con = dataSource.getConnection(); QueryRunner qr = new QueryRunner(); int row = qr.execute(con, sql); System.out.println("update: "+ row); } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(con); } } }
实现CommandLineRunner,实现方法,监听canal客户端。
package com.scbg.canal; import com.scbg.canal.client.CanalClient; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import javax.annotation.Resource; /** * @program: education * @description: * @author: WL * @create: 2020-07-10 10:58 **/ @SpringBootApplication public class CanalApplication implements CommandLineRunner { @Resource private CanalClient canalClient; public static void main(String[] args) { SpringApplication.run(CanalApplication.class,args); } @Override public void run(String... args) throws Exception { //项目启动,执行canal客户端监听 canalClient.run(); } }
D:\softwarefolder\Java\jdk1.8.0_181\bin\java.exe -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true “-javaagent:D:\softwarefolder\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=57506:D:\softwarefolder\IntelliJ IDEA 2019.3.3\bin” -Dfile.encoding=UTF-8 -classpath D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\charsets.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\deploy.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\javaws.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\jce.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\jfr.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\jsse.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\management-agent.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\plugin.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\resources.jar;D:\softwarefolder\Java\jdk1.8.0_181\jre\lib\rt.jar;D:\idea_workspace\education\canal_client\target\classes;D:\myRepository\org\springframework\boot\spring-boot-starter-web\2.2.1.RELEASE\spring-boot-starter-web-2.2.1.RELEASE.jar;D:\myRepository\org\springframework\boot\spring-boot-starter\2.2.1.RELEASE\spring-boot-starter-2.2.1.RELEASE.jar;D:\myRepository\org\springframework\boot\spring-boot\2.2.1.RELEASE\spring-boot-2.2.1.RELEASE.jar;D:\myRepository\org\springframework\boot\spring-boot-autoconfigure\2.2.1.RELEASE\spring-boot-autoconfigure-2.2.1.RELEASE.jar;D:\myRepository\org\springframework\boot\spring-boot-starter-logging\2.2.1.RELEASE\spring-boot-starter-logging-2.2.1.RELEASE.jar;D:\myRepository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\myRepository\org\apache\logging\log4j\log4j-to-slf4j\2.12.1\log4j-to-slf4j-2.12.1.jar;D:\myRepository\org\apache\logging\log4j\log4j-api\2.12.1\log4j-api-2.12.1.jar;D:\myRepository\org\slf4j\jul-to-slf4j\1.7.29\jul-to-slf4j-1.7.29.jar;D:\myRepository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\myRepository\org\springframework\spring-core\5.2.1.RELEASE\spring-core-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-jcl\5.2.1.RELEASE\spring-jcl-5.2.1.RELEASE.jar;D:\myRepository\org\yaml\snakeyaml\1.25\snakeyaml-1.25.jar;D:\myRepository\org\springframework\boot\spring-boot-starter-json\2.2.1.RELEASE\spring-boot-starter-json-2.2.1.RELEASE.jar;D:\myRepository\com\fasterxml\jackson\core\jackson-databind\2.10.0\jackson-databind-2.10.0.jar;D:\myRepository\com\fasterxml\jackson\core\jackson-annotations\2.10.0\jackson-annotations-2.10.0.jar;D:\myRepository\com\fasterxml\jackson\core\jackson-core\2.10.0\jackson-core-2.10.0.jar;D:\myRepository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.10.0\jackson-datatype-jdk8-2.10.0.jar;D:\myRepository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.10.0\jackson-datatype-jsr310-2.10.0.jar;D:\myRepository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.10.0\jackson-module-parameter-names-2.10.0.jar;D:\myRepository\org\springframework\boot\spring-boot-starter-tomcat\2.2.1.RELEASE\spring-boot-starter-tomcat-2.2.1.RELEASE.jar;D:\myRepository\org\apache\tomcat\embed\tomcat-embed-core\9.0.27\tomcat-embed-core-9.0.27.jar;D:\myRepository\org\apache\tomcat\embed\tomcat-embed-el\9.0.27\tomcat-embed-el-9.0.27.jar;D:\myRepository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.27\tomcat-embed-websocket-9.0.27.jar;D:\myRepository\org\springframework\boot\spring-boot-starter-validation\2.2.1.RELEASE\spring-boot-starter-validation-2.2.1.RELEASE.jar;D:\myRepository\jakarta\validation\jakarta.validation-api\2.0.1\jakarta.validation-api-2.0.1.jar;D:\myRepository\org\hibernate\validator\hibernate-validator\6.0.18.Final\hibernate-validator-6.0.18.Final.jar;D:\myRepository\org\jboss\logging\jboss-logging\3.4.1.Final\jboss-logging-3.4.1.Final.jar;D:\myRepository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\myRepository\org\springframework\spring-web\5.2.1.RELEASE\spring-web-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-beans\5.2.1.RELEASE\spring-beans-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-webmvc\5.2.1.RELEASE\spring-webmvc-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-aop\5.2.1.RELEASE\spring-aop-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-context\5.2.1.RELEASE\spring-context-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-expression\5.2.1.RELEASE\spring-expression-5.2.1.RELEASE.jar;D:\myRepository\mysql\mysql-connector-java\8.0.18\mysql-connector-java-8.0.18.jar;D:\myRepository\commons-dbutils\commons-dbutils\1.7\commons-dbutils-1.7.jar;D:\myRepository\org\springframework\boot\spring-boot-starter-jdbc\2.2.1.RELEASE\spring-boot-starter-jdbc-2.2.1.RELEASE.jar;D:\myRepository\com\zaxxer\HikariCP\3.4.1\HikariCP-3.4.1.jar;D:\myRepository\org\slf4j\slf4j-api\1.7.29\slf4j-api-1.7.29.jar;D:\myRepository\org\springframework\spring-jdbc\5.2.1.RELEASE\spring-jdbc-5.2.1.RELEASE.jar;D:\myRepository\org\springframework\spring-tx\5.2.1.RELEASE\spring-tx-5.2.1.RELEASE.jar;D:\myRepository\com\alibaba\otter\canal.client\1.1.0\canal.client-1.1.0.jar;D:\myRepository\com\alibaba\otter\canal.protocol\1.1.0\canal.protocol-1.1.0.jar;D:\myRepository\com\alibaba\otter\canal.common\1.1.0\canal.common-1.1.0.jar;D:\myRepository\io\netty\netty-all\4.1.43.Final\netty-all-4.1.43.Final.jar;D:\myRepository\org\apache\zookeeper\zookeeper\3.4.5\zookeeper-3.4.5.jar;D:\myRepository\org\jboss\netty\netty\3.2.2.Final\netty-3.2.2.Final.jar;D:\myRepository\com\101tec\zkclient\0.10\zkclient-0.10.jar;D:\myRepository\commons-io\commons-io\2.6\commons-io-2.6.jar;D:\myRepository\commons-codec\commons-codec\1.13\commons-codec-1.13.jar;D:\myRepository\com\alibaba\fastjson\1.2.28\fastjson-1.2.28.jar;D:\myRepository\com\google\guava\guava\18.0\guava-18.0.jar;D:\myRepository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\myRepository\org\slf4j\jcl-over-slf4j\1.7.29\jcl-over-slf4j-1.7.29.jar;D:\myRepository\org\springframework\spring-orm\5.2.1.RELEASE\spring-orm-5.2.1.RELEASE.jar;D:\myRepository\com\google\protobuf\protobuf-java\2.6.1\protobuf-java-2.6.1.jar;D:\myRepository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar com.scbg.canal.CanalApplication
. ____ _ __ _ _
/\ / ’ __ _ () __ __ _ \ \ \
( ( )__ | '_ | '| | ’ / ` | \ \ \
\/ )| |)| | | | | || (| | ) ) ) )
’ || .__|| ||| |__, | / / / /
=|_|======|/=////
:: Spring Boot :: (v2.2.1.RELEASE)
2020-07-10 14:08:15.142 INFO 14612 — [ main] com.scbg.canal.CanalApplication : Starting CanalApplication on DESKTOP-BNBOEF4 with PID 14612 (D:\idea_workspace\education\canal_client\target\classes started by 12601 in D:\idea_workspace\education)
2020-07-10 14:08:15.145 INFO 14612 — [ main] com.scbg.canal.CanalApplication : The following profiles are active: dev
2020-07-10 14:08:16.310 INFO 14612 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8020 (http)
2020-07-10 14:08:16.317 INFO 14612 — [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-07-10 14:08:16.318 INFO 14612 — [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.27]
2020-07-10 14:08:16.319 INFO 14612 — [ main] o.a.catalina.core.AprLifecycleListener : An older version [1.2.21] of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.23]
2020-07-10 14:08:16.319 INFO 14612 — [ main] o.a.catalina.core.AprLifecycleListener : Loaded APR based Apache Tomcat Native library [1.2.21] using APR version [1.6.5].
2020-07-10 14:08:16.319 INFO 14612 — [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
2020-07-10 14:08:16.319 INFO 14612 — [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2020-07-10 14:08:16.322 INFO 14612 — [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1a 20 Nov 2018]
2020-07-10 14:08:16.402 INFO 14612 — [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-07-10 14:08:16.402 INFO 14612 — [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1174 ms
2020-07-10 14:08:16.572 INFO 14612 — [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService ‘applicationTaskExecutor’
2020-07-10 14:08:16.740 INFO 14612 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8020 (http) with context path ‘’
2020-07-10 14:08:16.742 INFO 14612 — [ main] com.scbg.canal.CanalApplication : Started CanalApplication in 1.938 seconds (JVM running for 2.735)
2020-07-10 14:08:18.892 INFO 14612 — [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.
2020-07-10 14:08:18.907 ERROR 14612 — [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:787) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at com.scbg.canal.CanalApplication.main(CanalApplication.java:21) [classes/:na]
Caused by: com.alibaba.otter.canal.protocol.exception.CanalClientException: java.net.ConnectException: Connection refused: connect
at com.alibaba.otter.canal.client.impl.SimpleCanalConnector.doConnect(SimpleCanalConnector.java:190) ~[canal.client-1.1.0.jar:na]
at com.alibaba.otter.canal.client.impl.SimpleCanalConnector.connect(SimpleCanalConnector.java:114) ~[canal.client-1.1.0.jar:na]
at com.scbg.canal.client.CanalClient.run(CanalClient.java:45) ~[classes/:na]
at com.scbg.canal.CanalApplication.run(CanalApplication.java:26) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
… 5 common frames omitted
Caused by: java.net.ConnectException: Connection refused: connect
at sun.nio.ch.Net.connect0(Native Method) ~[na:1.8.0_181]
at sun.nio.ch.Net.connect(Net.java:454) ~[na:1.8.0_181]
at sun.nio.ch.Net.connect(Net.java:446) ~[na:1.8.0_181]
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648) ~[na:1.8.0_181]
at com.alibaba.otter.canal.client.impl.SimpleCanalConnector.doConnect(SimpleCanalConnector.java:149) ~[canal.client-1.1.0.jar:na]
… 9 common frames omitted
2020-07-10 14:08:18.910 INFO 14612 — [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService ‘applicationTaskExecutor’
Process finished with exit code 1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。