1肖油、zookeeper啟動(dòng)

每探索一門新技術(shù)的時(shí)候审孽,我們都會從方法的入口開始探索打颤,對于zookeeper也一樣瘸洛,zookeeper在啟動(dòng)時(shí)候是通過QuorumPeerMain來作為啟動(dòng)入口類。我們有必要知道在啟動(dòng)類啟動(dòng)時(shí),zookeeper做了哪些初始化和準(zhǔn)備工作。

public static void main(String[] args) {
    QuorumPeerMain main = new QuorumPeerMain();
    try {
        //zookeeper啟動(dòng)入口,初始化參數(shù)配置并啟動(dòng)zookeeper
        main.initializeAndRun(args);
    } catch (IllegalArgumentException e) {
        LOG.error("Invalid arguments, exiting abnormally", e);
        System.exit(2);
    } catch (ConfigException e) {
        LOG.error("Invalid config, exiting abnormally", e);
        System.exit(2);
    } catch (DatadirException e) {
        LOG.error("Unable to access datadir, exiting abnormally", e);
        System.exit(3);
    } catch (AdminServerException e) {
        LOG.error("Unable to start AdminServer, exiting abnormally", e);
        System.exit(4);
    } catch (Exception e) {
        LOG.error("Unexpected exception, exiting abnormally", e);
        System.exit(1);
    }
    LOG.info("Exiting normally");
    System.exit(0);
}

我們看到main方法里通過調(diào)用initializeAndRun開始進(jìn)行初始化配置和啟動(dòng)憎亚,所以我們跟進(jìn)去看下該方法的具體行為是做了什么陆爽?

 protected void initializeAndRun(String[] args)
        throws ConfigException, IOException, AdminServerException
    {
      //  1贡必、解析zoo.cfg配置文件利花,讀取配置文件中的KEY-value鍵值對挠乳,初始化QuorumPeerConfig 
        QuorumPeerConfig config = new QuorumPeerConfig();
        if (args.length == 1) {
            config.parse(args[0]);
        }

        //創(chuàng)建文件清理管理器,該清理器主要負(fù)責(zé)定期清理內(nèi)存快照文件和日志文件
        //snapRetainCount:至少保留文件個(gè)數(shù)
        //purgeInterval:定時(shí)任務(wù)間隔時(shí)間马靠,只有purgeInterval大于0第晰,該文件清理器才會開啟文件清理的定時(shí)任務(wù)
        DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config
                .getDataDir(), config.getDataLogDir(), config
                .getSnapRetainCount(), config.getPurgeInterval());
        purgeMgr.start();
        //quorumVerifier!=null && (!standaloneEnabled || quorumVerifier.getVotingMembers().size() > 1);
        //上面表示如果是集群配置的話,服務(wù)器將會集群方式啟動(dòng)
        /**zoo.cfg集群配置servers配置如下:
             servers.1=127.0.0.1:2287:3387
              servers.2=127.0.0.1:2288:3388
              servers.3=127.0.0.1:2289:3389
          ***/
        if (args.length == 1 && config.isDistributed()) {
            runFromConfig(config);//集群方式啟動(dòng)
        } else {
            ZooKeeperServerMain.main(args);//單機(jī)版啟動(dòng)
        }
    }

然后我們看下羽历,當(dāng)zookeeper以集群方式啟動(dòng)時(shí)疏尿,具體做了哪些準(zhǔn)備工作敌呈?

    public void runFromConfig(QuorumPeerConfig config)
            throws IOException, AdminServerException
    {
      try {
          //注冊日志管理(不用管)
          ManagedUtil.registerLog4jMBeans();
      } catch (JMException e) {
          LOG.warn("Unable to register log4j JMX control", e);
      }

      LOG.info("Starting quorum peer");
      try {
        
          ServerCnxnFactory cnxnFactory = null;
          ServerCnxnFactory secureCnxnFactory = null;
          //我們可以在zoo.cfg里通過clientPortAddress屬性來配置线脚,如果沒有配置clientPortAddress的話,默認(rèn)采用clientPort端口地址
          if (config.getClientPortAddress() != null) {
              //創(chuàng)建ServerCnxnFactory實(shí)例,ServerCnxnFactory主要負(fù)責(zé)跟客戶端進(jìn)行網(wǎng)絡(luò)通信抽诉,接收客戶端網(wǎng)絡(luò)請求唉窃,比如提交事務(wù)等矮嫉,默認(rèn)采用NIO昨寞。
              // 可以通過配置系統(tǒng)參數(shù)zookeeper.serverCnxnFactory來配置它實(shí)際實(shí)現(xiàn)的方式
              cnxnFactory = ServerCnxnFactory.createFactory();
              //根據(jù)端口號和maxClientCnxns初始化配置ServerCnxnFactory 羽峰,這兩個(gè)參數(shù)都可以通過zoo.cfg配置,分別是:
              //clientPortAddress||ClientPort:客戶端發(fā)送請求的端口
              //maxClientCnxns:最大并發(fā)數(shù),用來控制客戶端高并發(fā)
              cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(),false);
          }
          //和ServerCnxnFactory 一樣鼻种,通過在ZOO.CFG中配置secureClientPortAddress或secureClientPort篙贸,可都不配置
          if (config.getSecureClientPortAddress() != null) {
              secureCnxnFactory = ServerCnxnFactory.createFactory();
              secureCnxnFactory.configure(config.getSecureClientPortAddress(),
                      config.getMaxClientCnxns(),
                      true);
          }

          quorumPeer = getQuorumPeer();
          //創(chuàng)建內(nèi)存快照文件和事務(wù)文件日志文件的管理器FileTxnSnapLog爵川,該管理器提供了zookeeper上層服務(wù)跟底層數(shù)據(jù)庫存儲的對接入口碟案,
          // 他提供了一系列接口扮叨,用來訪問日志文件和內(nèi)存快站文件(具體提供了哪些訪問底層存儲文件的方法,我們后面會單獨(dú)抽出來探究一番)
          quorumPeer.setTxnFactory(new FileTxnSnapLog(
                      config.getDataLogDir(),
                      config.getDataDir()));
          quorumPeer.enableLocalSessions(config.areLocalSessionsEnabled());
          quorumPeer.enableLocalSessionsUpgrading(
              config.isLocalSessionsUpgradingEnabled());
          //配置選舉算法薪贫,不過現(xiàn)在一般都不配瞧省,默認(rèn)采用3
          quorumPeer.setElectionType(config.getElectionAlg());
          quorumPeer.setMyid(config.getServerId());
          quorumPeer.setTickTime(config.getTickTime());//設(shè)置心跳時(shí)間
          quorumPeer.setMinSessionTimeout(config.getMinSessionTimeout());//設(shè)置最小超時(shí)時(shí)間
          quorumPeer.setMaxSessionTimeout(config.getMaxSessionTimeout());//設(shè)置最小超時(shí)時(shí)間
          quorumPeer.setInitLimit(config.getInitLimit());//初時(shí)心跳次數(shù)
          quorumPeer.setSyncLimit(config.getSyncLimit());//同步心跳次數(shù)
          quorumPeer.setConfigFileName(config.getConfigFilename());
          //創(chuàng)建內(nèi)存數(shù)據(jù)庫ZKDatabase實(shí)例置森,創(chuàng)建該數(shù)據(jù)庫內(nèi)存實(shí)例時(shí)會注入一個(gè)DataTree建瘫,
          // DataTree為內(nèi)存數(shù)據(jù)庫內(nèi)真正作為保存內(nèi)存數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),維護(hù)了整個(gè)內(nèi)存數(shù)據(jù)庫中節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)泪勒,
          // 同時(shí)在創(chuàng)建DataTree時(shí)候會初始化創(chuàng)建根路徑/zookeeper和配額管理節(jié)點(diǎn)/zookeeper/quota
          quorumPeer.setZKDatabase(new ZKDatabase(quorumPeer.getTxnFactory()));
          quorumPeer.setQuorumVerifier(config.getQuorumVerifier(), false);
          if (config.getLastSeenQuorumVerifier()!=null) {
              quorumPeer.setLastSeenQuorumVerifier(config.getLastSeenQuorumVerifier(), false);
          }
          //初始化QuorumPeer的一些其它屬性,包括quorumCnxnThreadsSize(線程池QuerumServer manager線程池的初始線程數(shù))
          quorumPeer.initConfigInZKDatabase();
          quorumPeer.setCnxnFactory(cnxnFactory);
          ...
          quorumPeer.setQuorumListenOnAllIPs(config.getQuorumListenOnAllIPs());

          // sets quorum sasl authentication configurations
          quorumPeer.setQuorumSaslEnabled(config.quorumEnableSasl);
          if(quorumPeer.isQuorumSaslAuthEnabled()){
              quorumPeer.setQuorumServerSaslRequired(config.quorumServerRequireSasl);
              quorumPeer.setQuorumLearnerSaslRequired(config.quorumLearnerRequireSasl);
              quorumPeer.setQuorumServicePrincipal(config.quorumServicePrincipal);
              quorumPeer.setQuorumServerLoginContext(config.quorumServerLoginContext);
              quorumPeer.setQuorumLearnerLoginContext(config.quorumLearnerLoginContext);
          }
          //
          quorumPeer.setQuorumCnxnThreadsSize(config.quorumCnxnThreadsSize);
          quorumPeer.initialize();
          //啟動(dòng)quorumPeer并開始投票選舉
          quorumPeer.start();
          quorumPeer.join();
      } catch (InterruptedException e) {
          // warn, but generally this is ok
          LOG.warn("Quorum Peer interrupted", e);
      }
    }

我們再來看下它是如何創(chuàng)建ServerCnxnFactory呢?

  //創(chuàng)建ServerCnxnFactory實(shí)例由捎,ServerCnxnFactory主要負(fù)責(zé)跟客戶端進(jìn)行網(wǎng)絡(luò)通信邻奠,接收客戶端網(wǎng)絡(luò)請求贰镣,比如提交事務(wù)等,默認(rèn)采用NIO。
  // 可以通過配置系統(tǒng)參數(shù)zookeeper.serverCnxnFactory來配置它實(shí)際實(shí)現(xiàn)的方式
static public ServerCnxnFactory createFactory() throws IOException {
        //獲取系統(tǒng)參數(shù)zookeeper.serverCnxnFactory配置
        String serverCnxnFactoryName = System.getProperty(ZOOKEEPER_SERVER_CNXN_FACTORY);
        if (serverCnxnFactoryName == null) {//沒有配置則默認(rèn)采用NIOServerCnxnFactory
            serverCnxnFactoryName = NIOServerCnxnFactory.class.getName();
        }
        try {
            //創(chuàng)建NIOServerCnxnFactory
            ServerCnxnFactory serverCnxnFactory = (ServerCnxnFactory) Class.forName(serverCnxnFactoryName)
                    .getDeclaredConstructor().newInstance();
            LOG.info("Using {} as server connection factory", serverCnxnFactoryName);
            return serverCnxnFactory;
        } catch (Exception e) {
            IOException ioe = new IOException("Couldn't instantiate "
                    + serverCnxnFactoryName);
            ioe.initCause(e);
            throw ioe;
        }
    }

我么再看下quorumPeer.start做了哪些工作

 public synchronized void start() {
        //判斷集群配置是否包含本機(jī)myid
        if (!getView().containsKey(myid)) {
            throw new RuntimeException("My id " + myid + " not in the peer list");
         }
         //恢復(fù)內(nèi)存數(shù)據(jù)庫的數(shù)據(jù)
        loadDataBase();
        //啟動(dòng)網(wǎng)絡(luò)通信服務(wù)瞄勾,并監(jiān)聽客戶端的事務(wù)請求
        startServerCnxnFactory();
        try {
            adminServer.start();
        } catch (AdminServerException e) {
            LOG.warn("Problem starting AdminServer", e);
            System.out.println(e);
        }
        //開始進(jìn)行l(wèi)eader選舉
        startLeaderElection();
        //啟動(dòng)當(dāng)前線程(QuorumPeer本身也是一個(gè)線程).具體run做了哪些,我們后面會單獨(dú)討論,只需要知道它主要用來統(tǒng)計(jì)票數(shù),更新節(jié)點(diǎn)服務(wù)器的狀態(tài)
        super.start();
    }

總結(jié)

通過上面的代碼弥激,大概可以知道进陡,zookeeper服務(wù)器在啟動(dòng)時(shí)候主要做了以下工作:
  1、解析zoo.cfg配置文件微服,并初始化QuorumPeerConfig.
  2趾疚、創(chuàng)建文件清理器,根據(jù)配置參數(shù)purgeInterval決定是否開啟任務(wù)定時(shí)清理內(nèi)存快照文件和日志文件以蕴。
  3糙麦、創(chuàng)建并開啟用于和客戶端進(jìn)行網(wǎng)絡(luò)通信的ServerCnxnFactory,默認(rèn)是NIO的方式丛肮。
  4赡磅、創(chuàng)建日志快照和內(nèi)存快照的管理器FileTxnSnapLog,用來訪問日志文件和內(nèi)存快站文件宝与。
  5焚廊、創(chuàng)建并初始化內(nèi)存數(shù)據(jù)庫ZKDatabase
  6、恢復(fù)內(nèi)存數(shù)據(jù)庫數(shù)據(jù)
  7习劫、開始執(zhí)行l(wèi)eader選舉咆瘟。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诽里,隨后出現(xiàn)的幾起案子袒餐,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灸眼,死亡現(xiàn)場離奇詭異卧檐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)幢炸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門泄隔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拒贱,“玉大人宛徊,你說我怎么就攤上這事÷甙模” “怎么了闸天?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斜做。 經(jīng)常有香客問我苞氮,道長,這世上最難降的妖魔是什么瓤逼? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任笼吟,我火速辦了婚禮,結(jié)果婚禮上霸旗,老公的妹妹穿的比我還像新娘贷帮。我一直安慰自己,他們只是感情好诱告,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布撵枢。 她就那樣靜靜地躺著,像睡著了一般精居。 火紅的嫁衣襯著肌膚如雪锄禽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天靴姿,我揣著相機(jī)與錄音沃但,去河邊找鬼。 笑死佛吓,一個(gè)胖子當(dāng)著我的面吹牛绽慈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辈毯,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼坝疼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谆沃?” 一聲冷哼從身側(cè)響起钝凶,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后耕陷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掂名,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年哟沫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饺蔑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗜诀,死狀恐怖猾警,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情隆敢,我是刑警寧澤发皿,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站拂蝎,受9級特大地震影響穴墅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜温自,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一玄货、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悼泌,春花似錦松捉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至也拜,卻和暖如春以舒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背慢哈。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工蔓钟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卵贱。 一個(gè)月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓滥沫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親键俱。 傳聞我的和親對象是個(gè)殘疾皇子兰绣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)编振,斷路器缀辩,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 在ZooKeeper服務(wù)器啟動(dòng)期間,首先會進(jìn)行數(shù)據(jù)初始化工作,用于將存儲在磁盤上的數(shù)據(jù)文件加載到ZooKeeper...
    微子Lee閱讀 1,845評論 0 0
  • Zookeeper--Zookeeper是什么博客借鑒http://www.cnblogs.com/yuyijq/...
    Albert陳凱閱讀 6,033評論 1 36
  • 單機(jī)服務(wù)器啟動(dòng)ZooKeeper服務(wù)器啟動(dòng)臀玄,大體分為五個(gè)主要步驟:配置文件解析瓢阴、初始化數(shù)據(jù)管理器、初始化網(wǎng)絡(luò)I/O...
    微子Lee閱讀 782評論 0 0
  • 文 馮玙哲 會在夜里健无,輕輕的就觸碰到了你的臉頰溫暖的太陽里荣恐,總有無數(shù)柔情的光照耀我可愛的孩子,你會不會知道...
    馮玙哲閱讀 250評論 0 3