开发者社区> 问答> 正文

客户端高可用存在bug

问题场景

1,canal有两台服务器c1和c2,c1处于激活状态

2,客户端使用ClusterCanalConnector进行消费,也是两台服务器d1和d2,d1处于激活状态

3,c1发生宕机,此时d1会执行【ClusterCanalConnector】的restart()方法。restart中有三步:

第一步,disconnect,会释放running节点;

第二步,线程休眠5秒钟;

第三步,尝试重连,重连的时候会执行initRunning()方法。

4,在d1释放running节点后,d2会被立即触发,执行initRunning()方法,initRunning中也有两大步:

第一步,抢占running节点

第二步,执行processActiveEnter()方法,该方法肯定会报错,因为此时d2连接的canal也是c1,执行initRunning的zk线程会异常退出,此时d2的mutex变量仍然为false,并且没有释放running节点

5,d1后续的重连都没意义了,因为d2没有释放running节点,所以d1的mutext变成了false

6,最终结果是d1和d2都阻塞了

7,此时关闭d2,d1的initRunning方法会被触发,但d1的processActiveEnter方法仍然会报错,d1仍然无法恢复消费

原提问者GitHub用户lulu2panpan

展开
收起
绿子直子 2023-05-09 15:58:09 92 0
1 条回答
写回答
取消 提交回答
  • 看了下代码,如果第4步,d2启动链接时拿到的是c1,会在initRunning执行doConnect时执行失败,原本期望是通过客户端发起restart操作来处理,而d2因为是热备,可能是在异步initRunning回调时报错,无法触发client端的restart而导致长时间挂起

    想了下一种比较简单的改法

    1、initRunning针对执行异常时,主动释放running节点,通过异步回调来进行重试

    2、SimpleCanalConnector的doConnect方法动态获取address地址

    原回答者GitHub用户agapple

    2023-05-10 10:52:30
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载