最近一周在部署canal的HA集群版(v1.1.5),把遇到的问题和一些体会总结下,这篇文章不会以宏观的概念去理解canal的原理和设计理念,但通过实践,确实对canal的运维和设计有了更深刻的印象,而且如果你习惯于原来的单机部署模式,那么在部署集群版的时候,可能会觉得不适应。
那么部署HA集群版的原因是什么呢?首先如果按照传统的模式,增加一个instance需要手动拷贝一份配置,修改配置,然后重启服务,可操作性和可理解性非常差,而集群版有了UI控制台,非常的简单;其次canal service可以做到横向扩容,可用性上好了很多,当然canal admin本身还是一个单点。
canal从应用上主要包含三个概念,canal-service(canal.properties),canal-instance(canal.properties),canal-admin,前两者是一对多的概念,且是一个整体,比如一个service上可以部署多个instance;而canal-admin用于管理canal-service。
理解了这三者概念,那么首先配置的就是canal-admin,当然我不会贴一张图,官网上都有。
初始化数据库,为了管理service和instance,需要一个mysql数据库。
conf/application.yml中配置的adminUser和adminPasswd非常重要,首先它用于登录admin后台,但一旦修改后,这个配置对于admin后台登录就没有用了。
它重要的原因在于canal admin和canal service通信校验会用到,这后面会说。
接下去就是启动canal-admin,如果成功就在8089端口启动UI服务,强烈建议查看logs/admin.log日志,以便用于排查问题。
对于admin来说,有两个配置非常重要,就是config目录下的canal-template.properties,instance-template.properties,它们称为模板,也就是说service和instance服务本地配置文件都没有用了,它们都会读取admin的配置,这样说明service服务会非常的轻量。
其次我们启动canal-server服务。在运行的时候,首先要有一个基本配置文件。
官方让canal_local.properties覆盖canal.properties,进一步说明canal.properties的配置在集群版完全无用,这个local表明这是为了运行本地基础服务,建立和admin的通讯。
sh bin/startup.sh local或sh bin/startup.sh都可以启动。也强烈建议查看logs/canal/canal.log文件用于排查问题。
然后看看基础配置包含什么:
- # register ip
- canal.register.ip =
- # canal admin config
- canal.admin.manager = 127.0.0.1:8089
- canal.admin.port = 11110
- canal.admin.user = admin
- canal.admin.passwd = 4ACFE3202A5FF5CF467898FC58AAB1D615029441
- # admin auto register
- canal.admin.register.auto = true
- canal.admin.register.cluster =
canal.register.ip就是service的本地IP,canal.admin.manager是admin的远端地址,在启动的时候用于连接admin。
canal.admin.passwd密码非常重要,它会和admin做双向认证,canal-server会以这个密文和canal-admin做请求,同时canal-admin也会以密码原文生成加密串后和canal-server进行admin端口链接,所以这里一定要确保这两个密码内容的一致性。
canal.admin.port是service用于和admin建立通讯的端口。
canal.admin.register.cluster我没去试验,就是service启动的时候会自动加入admin配置的集群中(可以多个集群)。
启动的时候我遇到一个问题,提示Caused by: com.alibaba.otter.canal.common.CanalException: requestGet for canal config error: canal.properties config is empty错误。原因就在于service启动的时候会先admin拉取canal-template.properties配置。而我在admin启动后并没有立刻配置canal-template.properties(困惑的是canal-template.properties这个配置动作属主是配置集群,所以比较有疑惑性,但看到canal.admin.register.cluster,我觉得对于每一台service来说,它在设计中默认是只能配置为一个集群,从这个集群配置中拉取canal-template.properties,这样理解就比较合理了)
接下去说说如何在admin上管理集群、service、instance。
首先要建立集群,集群是通过zookeeper维护状态的,那存储什么了呢?个人觉得service连接admin的时候,会把存储状态放到zookeeper,admin通过zookeeper获取sercie的节点信息,当然可能还会存储其他的。
接下去配置service和instance,都是隶属关系。这里面重点说下自己的理解。
设想是建立二个集群,一个是qa集群,一个是online集群,但它们共用一群service,实际上在建立service的时候,如果发现节点(ip和port)已经使用过,就不允许建立了,联想下上面提到的canal.admin.register.cluster,进一步释然了。
这说明对于一个service节点来说,它只能连接一个集群,在这种情况下,如果为了区分qa集群和online集群,那么就要配置不同的service节点(ip和port不同就可以)。
也做了一些测试验证漂移,比如把某个service关闭,那么instance上的所属主机就会漂移。
最后说说service和instance配置,这里主要说基本的信息。
- # tcp bind ip
- canal.ip =
- # register ip to zookeeper
- canal.register.ip =
- canal.port = 11111
- canal.metrics.pull.port = 11112
- canal.zkServers = xwj-zookeeper-1.com:2181,xwj-zookeeper-2.com:2181,xwj-zookeeper-3.com:2181
- canal.serverMode = kafka
- canal.instance.global.spring.xml = classpath:spring/default-instance.xml
- kafka.bootstrap.servers = xwj-kafka-1.com:9092,xwj-kafka-2.com:9092,xwj-kafka-3.com:9092
- kafka.acks = all
现在看上去非常清晰,canal.port是本地服务的端口,canal.metrics.pull.port可以接入监控系统,使用kafka作为队列,default-instance.xml可以将pos信息同步到zookeeper,对于集群版我觉得只能配置它(没有测试),原因一台service挂了,接管的service必须知道消费到哪儿了。
- canal.instance.master.address=
- canal.instance.dbUsername=dts
- canal.instance.dbPassword=!xi5jie@com#
- canal.instance.connectionCharset = UTF-8
- canal.instance.filter.regex=.*\\..*
- canal.mq.partitionsNum=3
- canal.mq.partitionHash=test.table:id^name,.*\\..*
这个就更简单了,配置从那个数据库那个表监测binlog,然后同步到那个kafka topic中。