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