canal源码解析之canal.common

作者: holly_wang_王小飞 | 来源:发表于2016-12-29 18:00 被阅读265次

    canal启动的时候第二个启动的类是 CanalAlarmHandler 是canal的alarm报警机制。

    if (!alarmHandler.isStart()) {
        alarmHandler.start();
    }
    

    CanalAlarmHandler 是接口 定义了

        /**
         * 发送对应destination的报警
         * 
         * @param destination
         * @param msg
         */
        void sendAlarm(String destination, String msg);
    

    方法,具体是的实现类配置在file-instance.xml配置文件中

    <!-- 报警处理类 -->
    <bean id="alarmHandler" class="com.alibaba.otter.canal.common.alarm.LogAlarmHandler" />
    

    由于LogAlarmHandler在canal.common模块,所以这次整体分析下这个模块的代码。

    canal.common
    1.alarm包 **
    CanalAlarmHandler 接口定义了规范,
    LogAlarmHandler**实现具体的发送方法,看到源码中只是简单的打印了一条日志,所以我们可以自己去实现CanalAlarmHandler 类或者继承LogAlarmHandler 重写sendAlarm方法,实现发邮件等自己的业务通知报警方式。
    2.utils包
    AddressUtils 获取host的ip和address工具类。
    BooleanMutex类 厉害了,这个是用于并发控制的锁实现。根据其实现AQS的代码方式 知道这是个共享锁 关于这一块可以看前面的博客java.util.concurrent.locks包下的锁实现分析
    可以看下调用的地方 BooleanMutex调用的地方

    主要实现系统初始化/授权控制,没权限时阻塞等待。有权限时所有线程都可以快速通过,或者只初始化一次之类的并发问题,到时遇到对应的模块再分析之。
    CanalToStringStyle 主要用于输出格式的自定义,可以看ToStringBuilder ToStringStyle这篇文章的记录。

    JsonUtils明显 阿里的json处理工具,这里只是包装了下fastjson的方法。
    NamedThreadFactory 这个类用于创建线程的工厂,实现了ThreadFactory接口,主要是线程池编程中用到的,该类中还用到了ThreadGroup属性,将这些创建的类放到了一个ThreadGroup中,方便管理。

    final private ThreadGroup             group;
     public NamedThreadFactory(String name, boolean daemon){
            this.name = name;
            this.daemon = daemon;
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        }
    

    group的复制是System group组,也就是系统管理的组,这里还有个需要注意的是一个属性

        final private boolean                 daemon;
        public NamedThreadFactory(){
            this(DEFAULT_NAME, true);
        }
    
        public NamedThreadFactory(String name){
            this(name, true);
        }
    
    

    这里默认是true,可以看出创建的都是守护线程。守护线程是跟jvm的生命一致的。当没有非守护线程后jvm就退出了,守护线程也就退出了。
    ThreadGroup是为了方便线程管理出现了,可以统一设定线程组的一些属性,比如setDaemon,设置未处理异常的处理方法,设置统一的安全策略等等;也可以通过线程组方便的获得线程的一些信息。

    java中每一个ThreadGroup都可以包含一组的子线程和一组子线程组,在一个进程中线程组是以树形的方式存在,通常情况下根线程组是system线程组。system线程组下是main线程组,默认情况下第一级应用自己的线程组是通过main线程组创建出来的。看线下面例子和输出

    package com.alibaba.otter.canal.common;
    
    public class ThreadGroupDemo {
        public static void main(String[] args) {
            printGroupInfo(Thread.currentThread());
            
            Thread appThread = new Thread(new Runnable(){
                @Override
                public void run() {
                    for (int i=0;i<5;i++) {
                        System.out.println("do loop " + i);
                    }
                }
            });
            appThread.setName("appThread");
            appThread.start();
            printGroupInfo(appThread);
        }
        
        static void printGroupInfo(Thread t) {
            ThreadGroup group = t.getThreadGroup();
            System.out.println("thread " + t.getName() + " group name is " 
                    + group.getName()+ " max priority is " + group.getMaxPriority()
                    + " thread count is " + group.activeCount());
            
            ThreadGroup parent=group;
            do {
                ThreadGroup current = parent;
                parent = parent.getParent();
                if (parent == null) {
                    break;
                }
    
                System.out.println(current.getName() + "'s parent is " + parent.getName());
            } while (true);
            System.out.println("--------------------------");
        }
    }
    thread main group name is main max priority is 10 thread count is 1
    main's parent is system
    --------------------------
    thread appThread group name is main max priority is 10 thread count is 2
    main's parent is system
    --------------------------
    do loop 0
    do loop 1
    do loop 2
    do loop 3
    do loop 4
    

    关于Thread的setDaemon的作用可以看这篇文章Java中守护线程的总结(转) 这是我转的一篇文章,感觉写的好久不重复造轮子了。
    UriUtils 这个类主要做url参数的解析。我们可以以后用到自己的项目中去。
    3.zookeeper
    该包下主要指对zk操作用到的工具类。zk server运行时的内存数据,各种序列化等,最zk client方法的进一步包装。写zk 源码分析的时候再细入。
    4.剩下的三个类
    CanalLifeCycle 接口定义了canal中的生命周期方法,start stop 和isStart方法,好多涉及到启动停止的都会实现该类。AbstractCanalLifeCycle抽象类简单实现了CanalLifeCycle 接口,大多继承的子类都重写了该方法。
    CanalException 是定义的一个异常类继承了NestableRuntimeException类,比较简单。
    canal.common 完毕。。。。。。

    相关文章

      网友评论

        本文标题:canal源码解析之canal.common

        本文链接:https://www.haomeiwen.com/subject/vrftvttx.html