(四)、canal学习笔记之监听多数据库实例

前言

在前面章节中,我们写了一个canal c#版的客户端用来接受canal服务端发送过来的数据,但目前的客户端不完善,比如:不能断线重连、多个客户端代码重复等,因此,我们首先封装一个Helper类,代码如下:

class CanalHelper
{
    /// <summary>
    /// 启动
    /// </summary>
    /// <param name="simpleCanalOptions"></param>
    /// <param name="e">收到数据的回调处理</param>
    /// <returns></returns>
    public static async Task StartAsync(SimpleCanalOptions simpleCanalOptions, Action<CanalEventArg> e)
    {
        //1.初始化日志
        var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Debug)
                .AddFilter("System", LogLevel.Information)
                .AddConsole();
        });
        var logger = loggerFactory.CreateLogger<SimpleCanalConnection>();
        SimpleCanalConnection conn = null;
        try
        {
            //2.创建连接
            conn = new SimpleCanalConnection(simpleCanalOptions, logger);
            //连接到 Canal Server
            await conn.ConnectAsync();
            //订阅
            await conn.SubscribeAsync();
            new Thread(() =>
            {
                try
                {
                    //3.获取数据
                    while (true)
                    {
                        var msg = conn.GetAsync(1024).Result;
                        if (msg.Entries.Count <= 0)
                        {
                            Thread.Sleep(1000);
                            continue;
                        }
                        foreach (var entry in msg.Entries)
                        {
                            //不处理事务标记
                            if (entry.EntryType == EntryType.Transactionbegin || entry.EntryType == EntryType.Transactionend)
                            {
                                continue;
                            }
                            RowChange rowChange = RowChange.Parser.ParseFrom(entry.StoreValue);
                            foreach (var rowData in rowChange.RowDatas)
                            {
                                if (e != null)
                                {
                                    e.Invoke(new CanalEventArg()
                                    {
                                        DatabaseName = entry.Header.SchemaName,
                                        TableName = entry.Header.TableName,
                                        BeforeColumns = rowData.BeforeColumns.ToList(),
                                        AfterColumns = rowData.AfterColumns.ToList()
                                    });
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (conn != null)
                    {
                        conn.DisposeAsync().GetAwaiter();
                    }
                    logger.LogError(ex, "读取canal server数据失败");
                    Thread.Sleep(5000);
                    //重连
                    StartAsync(simpleCanalOptions, e).Wait();
                }
            }).Start();
        }
        catch (Exception ex)
        {
            if (conn != null)
            {
                await conn.DisposeAsync();
            }
            logger.LogError(ex, "连接canal server端失败");
            Thread.Sleep(5000);
            //重连
            await StartAsync(simpleCanalOptions, e);
        }
    }

    public class CanalEventArg
    {
        /// <summary>
        /// 数据库名称
        /// </summary>
        public string DatabaseName { get; set; }

        /// <summary>
        /// 表名
        /// </summary>
        public string TableName { get; set; }

        /// <summary>
        /// 变化之前的数据
        /// </summary>
        public List<Column> BeforeColumns { get; set; }

        /// <summary>
        /// 变化之后数据
        /// </summary>
        public List<Column> AfterColumns { get; set; }
    }
}

在main方法中添加以下代码

await CanalHelper.StartAsync(new SimpleCanalOptions("127.0.0.1", 11111, "1234"), (e) =>
{

});

Console.ReadKey();//阻止客户端退出

多数据库实例配置

多数据库实例配置主要分为以下两种情况:

  1. 多个数据库之间没有任何联系(垂直分库)
  2. 分库分表(多个数据库是一个逻辑库,水平分库)

垂直分库配置:

主要配置项在canal.properties中destinations配置节中

在这里插入图片描述
canal.destinations:当前server上部署的instance列表,多个用英文逗号隔开
canal.conf.dir:instance配置文件所在的路径
canal.auto.scan:是否开启自动扫描,true为开启
canal.auto.scan.interval:自动扫描的间隔时间,单位秒
由以上可知,我们可以先启动canal服务,然后动态添加instance配置,我们先启动canal服务
在这里插入图片描述
接着再启动三个客户端,分别监控本地端口为3306、3307、3308三个数据库实例,代码如下

static async Task Main(string[] args)
{

    await CanalHelper.StartAsync(new SimpleCanalOptions("127.0.0.1", 11111, "1234"), (e) =>//Destination默认为example
    {

    });

    await CanalHelper.StartAsync(new SimpleCanalOptions("127.0.0.1", 11111, "1235") { Destination = "example1" }, (e) =>
    {

    });

    await CanalHelper.StartAsync(new SimpleCanalOptions("127.0.0.1", 11111, "1236") { Destination = "example2" }, (e) =>
    {

    });

    Console.ReadKey();//阻止客户端退出
}

在conf目录下分别创建两个文件夹example1和example2,并且复制example中的instance.properties文件,并将监听的数据库信息修改好
example1:
在这里插入图片描述
example2:

在这里插入图片描述
接着依次修改3306、3307、3308中的数据,则对应的客户端就会收到修改的数据
3306:
在这里插入图片描述
3307:
在这里插入图片描述
3308:
在这里插入图片描述

水平分库(分库分表)配置

在上一章节中就有介绍到group-instance.xml文件专门用于分库分表场景,为了更好的演示,我们将前面配置的exmaple2和example3实例删除

  1. 首先需要调整group-instance.xml文件中的模板
    打开conf/spring/group-instance.xml文件
    在这里插入图片描述
    默认的模板中配置了两主两从的分库分表配置模板,但是我们目前有三个实例(三个分库),所以需要再复制一组
  • 添加一个eventParse
    在这里插入图片描述
  • 拷贝一组eventParse的bean节点,并命名为eventParse3
    在这里插入图片描述
  • 修改以下配置项
    在这里插入图片描述
    在这里插入图片描述
    group-instance.xml文件修改完后保存,接着再修改example的instance.properties文件,添加以下配置:
    在这里插入图片描述
canal.instance.master1.address=127.0.0.1:3306
canal.instance.master1.journal.name=
canal.instance.master1.position=
canal.instance.master1.timestamp=
canal.instance.master1.gtid=

canal.instance.master2.address=127.0.0.1:3307
canal.instance.master2.journal.name=
canal.instance.master2.position=
canal.instance.master2.timestamp=
canal.instance.master2.gtid=

canal.instance.master3.address=127.0.0.1:3308
canal.instance.master3.journal.name=
canal.instance.master3.position=
canal.instance.master3.timestamp=
canal.instance.master3.gtid=

再次启动canle服务端和客户端并修改三个数据库实例即可
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值