您的位置:首页 > 其它

[总结]单个jvm内canal-client不能同时消费多个destination错误排查

2018-01-17 16:02 357 查看


单个jvm内canal-client不能同时消费多个destination错误排查


背景

背景,在dev环境,我们想模拟单个canal-client 消费mysql 单实例-多db库的bin-log的场景。于是canal-server端的配置文件,配置成了3个destination,conf文件夹下的目录明细如下:
|- conf
|—- item/instance.properties
|—- settlement/instance.properties
|—- trade/instance.properties
|—-……

canal.properties文件中:canal.destinations=item,settlement,trade


canal-client 端使用如下代码进行订阅bin-log


package com.test.canal;
import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;

/**
* 集群模式的测试例子
*/
public class ClusterCanalClientDemo extends AbstractCanalClientTest {

public ClusterCanalClientDemo(String destination){
super(destination);
}

public static void main(String args[]) {

CanalConnector connectorItem = CanalConnectors.newClusterConnector("127.0.0.1:2181", "item", "", "");
final ClusterCanalClientDemo item = new ClusterCanalClientDemo("item");
item.setConnector(connectorItem);
item.start();

CanalConnector connectorSettlement = CanalConnectors.newClusterConnector("127.0.0.1:2181", "settlement", "", "");
final ClusterCanalClientDemo settlement = new ClusterCanalClientDemo("settlement");
settlement.setConnector(connectorSettlement);
settlement.start();

CanalConnector connectorTrade = CanalConnectors.newClusterConnector("127.0.0.1:2181", "trade", "", "");
final ClusterCanalClientDemo trade = new ClusterCanalClientDemo("trade");
trade.setConnector(connectorTrade);
trade.start();

Runtime.getRuntime().addShutdownHook(new Thread() {

public void run() {
try {
logger.info("## stop the canal client");
item.stop();
} catch (Throwable e) {
logger.warn("##something goes wrong when stopping canal:", e);
} finally {
logger.info("## canal client is down.");
}
}

});
}
}


按照预想,本来是server同时生产三个destination消息,然后client也同时消费三个destination中的消息。

but 由于对canal不是很熟悉,瞎子摸石头过河一样,每一步都是靠自我感觉去测试和验证。这其中肯定要遇到不少困难!



问题描述

当我运行上面的代码时,一个canal-client同时消费三个destination,订阅三个db库(item、settlement、trade)的bin-log,发现,总是只有两个destination能成功。而且成功的destination似乎是随机的,最重要的是没有任何地方有报错日志。这瞬间让人心情不好了。


问题排查

1.多次运行canal-client,发现简单的规律,item和settlement总是有一个消费正常,有一个消费失败。
2.于是认为,应该不是server端的问题。
3.接下来又把ClusterCanalClientDemo拆分成三个client同时运行,发现三个client都消费得好好的。
4.于是大胆得出一个结论,难道是canal-client 不支持同时消费大于2个以上destination?因为每次都只有2个destination能成功。
5.随后又觉得不科学,否则,一个destination就得单独起一个jvm来运行client,像dev,test这种环境,我岂不是要起很多个client来消费。
6.我再次仔细看了看server端配置。这回发现一些蛛丝马迹,item/instance.properties 和 settlement/instance.properties两个实例中的username和password是一样的。
7.最后,我抱着试一试的心态,重新为settlement创建一个新的账户,canal2/canal2,然后重新运行server,再重新运行client。
果然,三个destination都正常消费了。



结论

当canal-server配置多个instance时,使用的slaveId、username必须不一样,否则当同一个client消费多个destination的时候,会出现莫名其妙的问题。


备注

最后附上我的canal-server配置




item/instance.properties:

## mysql serverId
canal.instance.mysql.slaveId = 1251
###################### item 库 start ###########################
# position info
canal.instance.master.address = 127.0.0.1:3306

# username/password
canal.instance.dbUsername = canal
canal.instance.dbPassword = canal
canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8

# table regex
canal.instance.filter.regex = db_item.canal_test1,db_item.tb_student1
# table black regex
canal.instance.filter.black.regex = None


settlement/instance.properties:

## mysql serverId
canal.instance.mysql.slaveId = 1252
###################### item 库 start ###########################
# position info
canal.instance.master.address = 127.0.0.1:3306

# username/password
canal.instance.dbUsername = canal2
canal.instance.dbPassword = canal2
canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8

# table regex
canal.instance.filter.regex = db_settlement.canal_test2,db_settlement.tb_student2
# table black regex
canal.instance.filter.black.regex = None


trade/instance.properties:

## mysql serverId
canal.instance.mysql.slaveId = 1253
###################### item 库 start ###########################
# position info
canal.instance.master.address = 127.0.0.1:3306

# username/password
canal.instance.dbUsername = canal3
canal.instance.dbPassword = canal3
canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8

# table regex
canal.instance.filter.regex = db_trade.canal_test3,db_trade.tb_student3
# table black regex
canal.instance.filter.black.regex = None
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐