【Zookeeper】原始碼分析之伺服器(三)之LeaderZooKeeperServer

leesf發表於2017-03-07

一、前言

  前面分析了ZooKeeperServer原始碼,由於QuorumZooKeeperServer的原始碼相對簡單,於是直接分析LeaderZooKeeperServer。

二、LeaderZooKeeperServer原始碼分析

  2.1 類的繼承關係 

public class LeaderZooKeeperServer extends QuorumZooKeeperServer {}

  說明:LeaderZooKeeperServer繼承QuorumZooKeeperServer抽象類,其會繼承ZooKeeperServer中的很多方法。

  2.2 類的屬性  

public class LeaderZooKeeperServer extends QuorumZooKeeperServer {
    // 提交請求處理器
    CommitProcessor commitProcessor;
}

  說明:其只有一個CommitProcessor類,表示提交請求處理器,其在處理鏈中的位置位於ProposalRequestProcessor之後,ToBeAppliedRequestProcessor之前。

  2.3 類的建構函式

    LeaderZooKeeperServer(FileTxnSnapLog logFactory, QuorumPeer self,
            DataTreeBuilder treeBuilder, ZKDatabase zkDb) throws IOException {
        super(logFactory, self.tickTime, self.minSessionTimeout,
                self.maxSessionTimeout, treeBuilder, zkDb, self);
    }

  說明:其直接呼叫父類QuorumZooKeeperServer的建構函式,然後再呼叫ZooKeeperServer的建構函式,逐級構造。

  2.4 核心函式分析

  1. setupRequestProcessors函式  

    protected void setupRequestProcessors() {
        // 建立FinalRequestProcessor
        RequestProcessor finalProcessor = new FinalRequestProcessor(this);
        // 建立ToBeAppliedRequestProcessor
        RequestProcessor toBeAppliedProcessor = new Leader.ToBeAppliedRequestProcessor(
                finalProcessor, getLeader().toBeApplied);
        // 建立CommitProcessor
        commitProcessor = new CommitProcessor(toBeAppliedProcessor,
                Long.toString(getServerId()), false);
        // 啟動CommitProcessor
        commitProcessor.start();
        // 建立ProposalRequestProcessor
        ProposalRequestProcessor proposalProcessor = new ProposalRequestProcessor(this,
                commitProcessor);
        // 初始化ProposalProcessor
        proposalProcessor.initialize();
        // firstProcessor為PrepRequestProcessor
        firstProcessor = new PrepRequestProcessor(this, proposalProcessor);
        // 啟動PrepRequestProcessor
        ((PrepRequestProcessor)firstProcessor).start();
    }

  說明:該函式表示建立處理鏈,可以看到其處理鏈的順序為PrepRequestProcessor -> ProposalRequestProcessor -> CommitProcessor -> Leader.ToBeAppliedRequestProcessor -> FinalRequestProcessor。

  2. registerJMX函式 

    protected void registerJMX() {
        // register with JMX
        try {
            // 建立DataTreeBean
            jmxDataTreeBean = new DataTreeBean(getZKDatabase().getDataTree());
            // 進行註冊
            MBeanRegistry.getInstance().register(jmxDataTreeBean, jmxServerBean);
        } catch (Exception e) {
            LOG.warn("Failed to register with JMX", e);
            jmxDataTreeBean = null;
        }
    }

  說明:該函式用於註冊JMX服務,首先使用DataTree初始化DataTreeBean,然後使用DataTreeBean和ServerBean呼叫register函式進行註冊,其原始碼如下 

    public void register(ZKMBeanInfo bean, ZKMBeanInfo parent)
        throws JMException
    {
        // 確保bean不為空
        assert bean != null;
        String path = null;
        if (parent != null) { // parent(ServerBean)不為空
            // 通過parent從bean2Path中獲取path
            path = mapBean2Path.get(parent);
            // 確保path不為空
            assert path != null;
        }
        // 補充為完整的路徑
        path = makeFullPath(path, parent);
        if(bean.isHidden())
            return;
        // 使用路徑來建立名字
        ObjectName oname = makeObjectName(path, bean);
        try {
            // 註冊Server
            mBeanServer.registerMBean(bean, oname);
            // 將bean和對應path放入mapBean2Path
            mapBean2Path.put(bean, path);
            // 將name和bean放入mapName2Bean
            mapName2Bean.put(bean.getName(), bean);
        } catch (JMException e) {
            LOG.warn("Failed to register MBean " + bean.getName());
            throw e;
      

  說明:可以看到會通過parent來獲取路徑,然後建立名字,然後註冊bean,之後將相應欄位放入mBeanServer和mapBean2Path中,即完成註冊過程。

  3. unregisterJMX函式  

    protected void unregisterJMX() {
        // unregister from JMX
        try {
            if (jmxDataTreeBean != null) {
                // 取消註冊
                MBeanRegistry.getInstance().unregister(jmxDataTreeBean);
            }
        } catch (Exception e) {
            LOG.warn("Failed to unregister with JMX", e);
        }
        jmxDataTreeBean = null;
    }

  說明:該函式用於取消註冊JMX服務,其會呼叫unregister函式,其原始碼如下 

    public void unregister(ZKMBeanInfo bean) {
        if(bean==null)
            return;
        // 獲取對應路徑
        String path=mapBean2Path.get(bean);
        try {
            // 取消註冊
            unregister(path,bean);
        } catch (JMException e) {
            LOG.warn("Error during unregister", e);
        }
        // 從mapBean2Path和mapName2Bean中移除bean
        mapBean2Path.remove(bean);
        mapName2Bean.remove(bean.getName());
    }

  說明:unregister與register的過程恰好相反,是移除bean的過程。

三、總結

  本篇學習了LeaderZooKeeperServer的原始碼,其原始碼非常簡單,主要涉及到註冊和取消註冊服務,其大部分邏輯可以直接使用ZooKeeperServer中的方法,也謝謝各位園友的觀看~

相關文章