一、前言
前面分析了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中的方法,也謝謝各位園友的觀看~