饥人谷技术博客大数据,机器学习,人工智能技术干货

zk源码阅读25:服务器异常报警,关闭机制

2017-07-30  本文已影响434人  赤子心_d709

摘要

本节讲解ZooKeeperServer类中的异常报警,关闭机制,在其他地方都没有找到类似解析以及源码说明。
这里自己分析源码,进行展开

ZooKeeperServerListener,作为服务器监听器,主要函数notifyStopping设置server状态为ERROR
ZooKeeperCriticalThread,作为zk危机线程,提供有处理异常的方式,即调用ZooKeeperServerListener.notifyStopping
ZooKeeperServerShutdownHandler,在zk状态为ERROR或SHUTDOWN时,完成zk的关闭操作
ZooKeeperServer的异常报警,关闭机制讲解

状态监听器

主要讲解接口ZooKeeperServerListener以及实现类ZooKeeperServerListenerImpl


监听器与服务器关系类图.png

接口ZooKeeperServerListener

方法如下

    void notifyStopping(String threadName, int errorCode);//用于在线程发生严重问题时,通知server

实现类ZooKeeperServerListenerImpl

    private final ZooKeeperServer zkServer;

    ZooKeeperServerListenerImpl(ZooKeeperServer zkServer) {
        this.zkServer = zkServer;
    }

    @Override
    public void notifyStopping(String threadName, int exitCode) {
        LOG.info("Thread {} exits, error code {}", threadName, exitCode);
        zkServer.setState(State.ERROR);//ZooKeeperServer设置对应状态即可
    }

这里只是调用 zkServer.setState(State.ERROR),具体监听到ERROR时该怎么干,是在zkserver中完成的事情,这里只监听和通知

上面有notifyStopping这个方法,那么这个方法在何时被调用呢?

报警危机线程ZooKeeperCriticalThread

ZooKeeperServerListener#notifyStopping何时被调用呢,就在ZooKeeperCriticalThread中
备注:这个中文名是我自己起的。。。
类图如下

ZooKeeperCriticalThread类图

源码如下,很简单

    /**
 * Represents critical thread. When there is an uncaught exception thrown by the
 * thread this will exit the system.
 */
public class ZooKeeperCriticalThread extends ZooKeeperThread {
    private static final Logger LOG = LoggerFactory
            .getLogger(ZooKeeperCriticalThread.class);
    private final ZooKeeperServerListener listener;

    public ZooKeeperCriticalThread(String threadName,
            ZooKeeperServerListener listener) {
        super(threadName);//父类是个thread
        this.listener = listener;//设置监听器实例
    }

    /**
     * This will be used by the uncaught exception handler and make the system
     * exit.
     * 
     * @param threadName
     *            - thread name
     * @param e
     *            - exception object
     */
    @Override
    protected void handleException(String threadName, Throwable e) {//处理异常
        LOG.error("Severe unrecoverable error, from thread : {}", threadName, e);
        listener.notifyStopping(threadName, ExitCode.UNEXPECTED_ERROR);//观察者模式,调用监听器的对应逻辑
    }
}

这里通过观察者模式,当ZooKeeperCriticalThread的实例遇到异常时,调用handleException,会给对应的监听器通知,完成notifyStopping的操作

ZooKeeperServerShutdownHandler

这个类图都不用画了,直接源码

    class ZooKeeperServerShutdownHandler {
    private final CountDownLatch shutdownLatch;

    ZooKeeperServerShutdownHandler(CountDownLatch shutdownLatch) {
        this.shutdownLatch = shutdownLatch;
    }

    /**
     * This will be invoked when the server transition to a new server state.
     *
     * @param state new server state
     */
    void handle(State state) {
        if (state == State.ERROR || state == State.SHUTDOWN) {
            shutdownLatch.countDown();
        }
    }
}

就是说,关闭处理器handle,就是把一个计时器-1

异常报警,关闭机制流程

这里以例子为说明,入口以ZooKeeperCriticalThread的一个子类为例,如SessionTrackerImpl好了,源码之前也讲解过

1.异常触发

SessionTrackerImpl#run
调用

    catch (InterruptedException e) {
            handleException(this.getName(), e);
        }

2.调用ZooKeeperCriticalThread#handleException

    @Override
    protected void handleException(String threadName, Throwable e) {//处理异常
        LOG.error("Severe unrecoverable error, from thread : {}", threadName, e);
        listener.notifyStopping(threadName, ExitCode.UNEXPECTED_ERROR);//观察者模式,调用监听器的对应逻辑
    }

3.监听器通知stop:ZooKeeperServerListener#notifyStopping

实现类ZooKeeperServerListenerImpl#notifyStopping

    @Override
    public void notifyStopping(String threadName, int exitCode) {
        LOG.info("Thread {} exits, error code {}", threadName, exitCode);
        zkServer.setState(State.ERROR);//ZooKeeperServer设置对应状态即可
    }

4.zkServer设置状态:ZooKeeperServer#setState

    protected void setState(State state) {//根据zkShutdownHandler处理state
        this.state = state;
        // Notify server state changes to the registered shutdown handler, if any.
        if (zkShutdownHandler != null) {
            zkShutdownHandler.handle(state);
        } else {
            LOG.error("ZKShutdownHandler is not registered, so ZooKeeper server "
                    + "won't take any action on ERROR or SHUTDOWN server state changes");
        }
    }

5.zkShutdownHandler处理state:ZooKeeperServerShutdownHandler#handle

    void handle(State state) {
        if (state == State.ERROR || state == State.SHUTDOWN) {
            shutdownLatch.countDown();
        }
    }

6.计时器到0,停止server

这一部分代码在zkServer外层,在ZooKeeperServerMain#runFromConfig中

zkServer与计时器完成server停止

也就是启动时,zkServer有一个计时器为1,当遇到严重异常时,计时器-1变为0,就调用ZooKeeperServerMain#shutdown

ZooKeeperServerMain#shutdown这里不展开,讲到ServerCnxnFactory再讲

思考

遇到严重异常时,server的关闭流程调用链总结

遇到严重异常 -> ZooKeeperCriticalThread#handleException -> ZooKeeperServerListener#notifyStopping -> ZooKeeperServer#setState -> ZooKeeperServerShutdownHandler#handle -> 计数器为0 -> ZooKeeperServerMain#shutdown

ZooKeeperCriticalThread,ZooKeeperServerListener,ZooKeeperServerShutdownHandler三个类的作用总结

  ZooKeeperCriticalThread:表明了哪些入口的异常可以算作是严重的异常,能够让server关闭的,并且handleException方法完成对ZooKeeperServerListener的调用
  ZooKeeperServerListener:表示接收到异常时,通知zk状态变更为ERROR
  ZooKeeperServerShutdownHandler:用于处理zk为ERROR和SHUTDOWN状态时,计数器-1

refer

上一篇 下一篇

猜你喜欢

热点阅读