canal的遠程配置canal.instance.global.mode = manager。。。canal源碼追蹤解析

一、canal的程序入口

在官網給的GitHub裏面的deployer模塊裏面,官網:https://github.com/alibaba/canal/tree/master/deployer

其中的main方法在:com.alibaba.otter.canal.deployer.CanalLauncher類裏面

二、加載canal的全局配置文件

追蹤源碼發現canal加載配置文件有兩種方法:一種加載的是本地的./conf/canal.properties;另一種是加載一個指定數據庫的某個字段的值。第一種:稱爲本地加載,第二種是遠程加載。

1、本地加載(默認加載方式)

官網的簡易教程就是本地加載的方式:https://github.com/alibaba/canal

2、遠程加載

遠程加載的配置內容是在一個canal_manager的數據庫裏面,裏面有canal_config、canal_instance_config表

(1)、配置遠程加載的數據庫的信息,修改./conf/canal.properties文件裏面的前三行(加載了遠程配置文件的就會覆蓋本地的)

canal.manager.jdbc.url=jdbc:mysql://127.0.0.1:3306/canal_manager?useUnicode=true&characterEncoding=UTF-8
canal.manager.jdbc.username=root
canal.manager.jdbc.password=121212

改成自己的數據庫,用戶和密碼(去掉備註),默認數據庫是canal_manager

 

(2)、創建遠程數據庫和表

create database if not EXISTS canal_manager;

create table if not EXISTS canal_manager.canal_config(
id BIGINT,
name VARCHAR(20),
content LONGTEXT,
modified_time TIMESTAMP
);

create table if not EXISTS canal_manager.canal_instance_config(
id BIGINT,
name VARCHAR(20),
content LONGTEXT,
modified_time TIMESTAMP
);

其中canal_config裏面的content值就是canal.properties的內容,並且這個表的數據只能有一行,id必須是1

其中canal_instance_config裏面的content的值是instance.properties的內容,instance的個數就是數據的行數,也就是每一行對應一個instance。這樣在數據庫裏面修改content的值就可以實現動態的遠程的加載配置文件。(配置的這個數據庫服務和同步的數據庫服務不是一個,ip不一樣)

三、官網給的配置方式

1、canal配置方式有兩種:

  1. ManagerCanalInstanceGenerator: 基於manager管理的配置方式,目前alibaba內部配置使用這種方式。大家可以實現CanalConfigClient,連接各自的管理系統,即可完成接入。
  2. SpringCanalInstanceGenerator:基於本地spring xml的配置方式,目前開源版本已經自帶該功能所有代碼,建議使用

針對於以上兩種方式:網上更多的是第二種,目前沒有看到任何關於第一種manager的配置,以下是個人對於manager的配置。

2、manager配置

這個過程需要修改源碼,準備工作需要先把官網的源碼下載到本地,源碼clone地址:https://github.com/alibaba/canal.git

(1)、修改canal.properties文件

canal.instance.global.mode = manager
canal.instance.global.lazy = false

(2)、重寫com.alibaba.otter.canal.instance.manager.CanalConfigClient類(在instance裏面)

public class CanalConfigClient {

    /**
     * 根據對應的destinantion查詢Canal信息
     */
    public Canal findCanal(String destination) {
        // TODO 根據自己的業務實現
        //獲取Apollo的配置
        System.setProperty("app.id","canal");
        System.setProperty("apollo.cluster","default");
        System.setProperty("apollo.meta","http://*.*.*.*:8080,http://*.*.*.*:8080");
        Config config = ConfigService.getConfig(destination+".properties"); //config instance is singleton for each namespace and is never null
        Long slaveId = Long.parseLong(config.getProperty("canal.instance.mysql.slaveId", "123456"));
        String USERNAME = config.getProperty("canal.instance.dbUsername", "canal");
        String PASSWORD = config.getProperty("canal.instance.dbPassword", "canal");
        String MYSQL_ADDRESS = config.getProperty("canal.instance.master.address", "*.*.*.*:3306").split(":")[0];
        int port = Integer.parseInt(config.getProperty("canal.instance.master.address", "*.*.*.*:3306").split(":")[1]);


        Canal canal = new Canal();
        canal.setId(1L);
        canal.setName(destination);
        canal.setDesc("test");

        CanalParameter parameter = new CanalParameter();

        parameter.setZkClusters(Arrays.asList("127.0.0.1:2188"));
        parameter.setMetaMode(CanalParameter.MetaMode.MEMORY);
        parameter.setHaMode(CanalParameter.HAMode.HEARTBEAT);
        parameter.setIndexMode(CanalParameter.IndexMode.MEMORY);

        parameter.setStorageMode(CanalParameter.StorageMode.MEMORY);
        parameter.setMemoryStorageBufferSize(32 * 1024);

        parameter.setSourcingType(CanalParameter.SourcingType.MYSQL);
        parameter.setDbAddresses(Arrays.asList(new InetSocketAddress(MYSQL_ADDRESS, 3306),
                new InetSocketAddress(MYSQL_ADDRESS, 3306)));
        parameter.setDbUsername(USERNAME);
        parameter.setDbPassword(PASSWORD);
        //parameter.setPositions(Arrays.asList("{\"journalName\":\"mysql-bin.000001\",\"position\":6163L,\"timestamp\":1322803601000L}",
        //        "{\"journalName\":\"mysql-bin.000001\",\"position\":6163L,\"timestamp\":1322803601000L}"));


        System.out.println(USERNAME+PASSWORD);
        parameter.setSlaveId(1234L);

        parameter.setDefaultConnectionTimeoutInSeconds(30);
        parameter.setConnectionCharset("UTF-8");
        parameter.setConnectionCharsetNumber((byte) 33);
        parameter.setReceiveBufferSize(8 * 1024);
        parameter.setSendBufferSize(8 * 1024);

        parameter.setDetectingEnable(false);
        parameter.setDetectingIntervalInSeconds(10);
        parameter.setDetectingRetryTimes(3);
        //parameter.setDetectingSQL(DETECTING_SQL);
        canal.setCanalParameter(parameter);

       /* System.out.println(username+password+host+port);
        CanalParameter canalParameter = new CanalParameter();
        canalParameter.setSlaveId(slaveId);
        canalParameter.setDbUsername(username);
        canalParameter.setDbPassword(password);
        canalParameter.setIndexMode(CanalParameter.IndexMode.MEMORY);
        List<InetSocketAddress> dbAddresses = new ArrayList<>();
        dbAddresses.add(new InetSocketAddress(host,port));
        canalParameter.setDbAddresses(dbAddresses);
        canal.setCanalParameter(canalParameter);
        canal.setName(destination);*/
        return  canal;
    }

    /**
     * 根據對應的destinantion查詢filter信息
     */
    public String findFilter(String destination) {
        // TODO 根據自己的業務實現
        Config config = ConfigService.getConfig(destination+".properties");
        return config.getProperty("canal.instance.filter.regex",".*\\..*");
    }
}

這兩個方法的實現比較簡單,但是在運行不成功,可能官網給的源碼的關於manager的不是太全,畢竟阿里自己用的是manager配置文件的方式。官網也推薦使用spring的方式,自己修改源碼,用manager的方式總是會有意想不到的問題(也可能自己解讀源碼不全)。

四、總結

對於canal來說配置文件有兩部分,一個是:全局的canal.properties(也可以說是canal-server配置),另一個是:instance.properties(也可以說是canal-client配置,也即instance配置)

總的來說有四種加載配置文件的方式:

1、本地加載+spring:默認加載../conf下的所有配置文件,canal.instance.global.mode = spring

2、本地加載+manager:默認加載../conf下的所有配置文件,canal.instance.global.mode = manager,需要重寫CanalConfigClient類

3、遠程加載+spring:需要在數據庫配置,canal_instance_config表裏面canal.instance.global.mode = spring

4、遠程加載+manager:需要在數據庫配置,canal_instance_config表裏面canal.instance.global.mode = manager,需要重寫CanalConfigClient類

 

個人提醒:重寫CanalConfigClient類比較複雜,有寫的可以交流一下:QQ羣

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章