国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Zookeeper

背景介紹

ZooKeeper可以以standalone,偽分布式和分布式三種方式部署.standalone模式下只有一臺(tái)機(jī)器作為服務(wù)器,喪失了ZooKeeper高可用的特點(diǎn).偽分布式是在一臺(tái)電腦上使用不同端口啟動(dòng)多個(gè)ZooKeeper服務(wù)器.分布式是使用多個(gè)機(jī)器,每臺(tái)機(jī)器上部署一個(gè)ZooKeeper服務(wù)器,即使有服務(wù)器宕機(jī),只要少于半數(shù),ZooKeeper集群依然可以正常對(duì)外提供服務(wù).
ZooKeeper以standalone模式啟動(dòng)只需啟動(dòng)對(duì)客戶端提供服務(wù)的組件,無需啟動(dòng)集群內(nèi)部通信組件,較為簡單,因此先從standalone模式開始介紹.

整體架構(gòu)


Zookeeper整體架構(gòu)如上圖,其中包括ServerCnxnFactory,SessionTracker,RequestProcessor,FileTxnSnapLog等眾多組件,這些組件都會(huì)在日后一一介紹.

啟動(dòng)流程概述

standalone模式啟動(dòng)主要包括如下幾個(gè)步驟:

  1. 配置文件解析

  2. 創(chuàng)建并啟動(dòng)歷史文件清理器

  3. 初始化數(shù)據(jù)管理器

  4. 注冊(cè)shutdownHandler

  5. 啟動(dòng)Admin server

  6. 創(chuàng)建并啟動(dòng)網(wǎng)絡(luò)IO管理器

  7. 啟動(dòng)ZooKeeperServer

  8. 創(chuàng)建并啟動(dòng)secureCnxnFactory

  9. 創(chuàng)建并啟動(dòng)ContainerManager

源碼如下:

protected void initializeAndRun(String[] args)throws ConfigException, IOException, AdminServerException {//1.解析配置文件QuorumPeerConfig config = new QuorumPeerConfig();if (args.length == 1) { config.parse(args[0]); }// Start and schedule the the purge task//2.創(chuàng)建并啟動(dòng)歷史文件清理器(對(duì)事務(wù)日志和快照數(shù)據(jù)文件進(jìn)行定時(shí)清理)DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config .getDataDir(), config.getDataLogDir(), config .getSnapRetainCount(), config.getPurgeInterval()); purgeMgr.start();if (args.length == 1 && config.isDistributed()) {//集群啟動(dòng)runFromConfig(config); } else {//單機(jī)啟動(dòng)LOG.warn('Either no config or no quorum defined in config, running ' ' in standalone mode');// there is only server in the quorum -- run as standaloneZooKeeperServerMain.main(args); } }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

    /**     * Run from a ServerConfig.     *     * @param config ServerConfig to use.     * @throws IOException     * @throws AdminServerException     */public void runFromConfig(ServerConfig config)throws IOException, AdminServerException {        LOG.info('Starting server');        FileTxnSnapLog txnLog = null;try {//3.創(chuàng)建ZooKeeper數(shù)據(jù)管理器txnLog = new FileTxnSnapLog(config.dataLogDir, config.dataDir);final ZooKeeperServer zkServer = new ZooKeeperServer(txnLog,                    config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, null);            txnLog.setServerStats(zkServer.serverStats());//4.注冊(cè)shutdownHandler,在ZooKeeperServer的狀態(tài)變化時(shí)調(diào)用shutdownHandler的handle()final CountDownLatch shutdownLatch = new CountDownLatch(1);            zkServer.registerServerShutdownHandler(new ZooKeeperServerShutdownHandler(shutdownLatch));//5.啟動(dòng)Admin serveradminServer = AdminServerFactory.createAdminServer();            adminServer.setZooKeeperServer(zkServer);            adminServer.start();//6.創(chuàng)建并啟動(dòng)網(wǎng)絡(luò)IO管理器boolean needStartZKServer = true;if (config.getClientPortAddress() != null) {                cnxnFactory = ServerCnxnFactory.createFactory();                cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), false);//7.此方法除了啟動(dòng)ServerCnxnFactory,還會(huì)啟動(dòng)ZooKeepercnxnFactory.startup(zkServer);// zkServer has been started. So we don't need to start it again in secureCnxnFactory.needStartZKServer = false;            }//8.創(chuàng)建并啟動(dòng)secureCnxnFactory if (config.getSecureClientPortAddress() != null) {                secureCnxnFactory = ServerCnxnFactory.createFactory();                secureCnxnFactory.configure(config.getSecureClientPortAddress(), config.getMaxClientCnxns(), true);                secureCnxnFactory.startup(zkServer, needStartZKServer);            }//9.創(chuàng)建并啟動(dòng)ContainerManagercontainerManager = new ContainerManager(zkServer.getZKDatabase(), zkServer.firstProcessor,                    Integer.getInteger('znode.container.checkIntervalMs', (int) TimeUnit.MINUTES.toMillis(1)),                    Integer.getInteger('znode.container.maxPerMinute', 10000)            );            containerManager.start();// Watch status of ZooKeeper server. It will do a graceful shutdown// if the server is not running or hits an internal error.//服務(wù)器正常啟動(dòng)時(shí),運(yùn)行到此處阻塞,只有server的state變?yōu)镋RROR或SHUTDOWN時(shí)繼續(xù)運(yùn)行后面的代碼shutdownLatch.await();            shutdown();if (cnxnFactory != null) {                cnxnFactory.join();            }if (secureCnxnFactory != null) {                secureCnxnFactory.join();            }if (zkServer.canShutdown()) {                zkServer.shutdown(true);            }        } catch (InterruptedException e) {// warn, but generally this is okLOG.warn('Server interrupted', e);        } finally {if (txnLog != null) {                txnLog.close();            }        }    }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 74

  • 75

  • 76

ZooKeeperstandalone啟動(dòng)共有9個(gè)步驟,其中有些步驟還有子步驟,有些步驟還會(huì)啟動(dòng)線程.因此下文中只會(huì)對(duì)一些簡單的步驟進(jìn)行介紹,復(fù)雜的步驟留作日后補(bǔ)充,接下來我們就分別看下這9個(gè)步驟.

解析配置文件

ZooKeeper啟動(dòng)時(shí)會(huì)讀取配置文件,默認(rèn)讀取$ZK_HOME/conf/zoo.cfg,其將文件解析為java.util.Properties,根據(jù)Properties中鍵值對(duì)的key設(shè)置相應(yīng)value.

創(chuàng)建并啟動(dòng)歷史文件清理器

ZooKeeper雖然是一個(gè)內(nèi)存數(shù)據(jù)庫,但是其通過快照和事務(wù)日志提供了持久化的功能.在ZooKeeper啟動(dòng)時(shí),會(huì)根據(jù)快照和事務(wù)日志恢復(fù)數(shù)據(jù),重建內(nèi)存數(shù)據(jù)庫;每次寫操作提交時(shí),會(huì)在事務(wù)日志中增加一條記錄,表明此次寫操作更改了哪些數(shù)據(jù);在進(jìn)行snapCount次事務(wù)之后,將內(nèi)存數(shù)據(jù)庫所有節(jié)點(diǎn)的數(shù)據(jù)和當(dāng)前會(huì)話信息生成一個(gè)快照.
ZooKeeper的事務(wù)日志類似于MySQL的redolog,若每次寫操作后直接將數(shù)據(jù)寫到磁盤上,則會(huì)存在大量的磁盤隨機(jī)讀寫,若是寫事務(wù)日志,則將磁盤隨機(jī)讀寫轉(zhuǎn)換為順序讀寫.保證了數(shù)據(jù)的持久性的同時(shí)也兼顧了性能.
隨著時(shí)間的推移,會(huì)生成越來越多的快照和事務(wù)日志文件,為了定時(shí)清理無效日志,DatadirCleanupManager啟動(dòng)定時(shí)任務(wù)完成日志文件的清理.

相關(guān)配置

屬性名對(duì)應(yīng)配置配置方式默認(rèn)值含義
snapRetainCountautopurge.snapRetainCount配置文件3清理后保留的快照文件個(gè)數(shù),最小值為3,若設(shè)置為<3的數(shù),則修改為3
purgeIntervalautopurge.purgeInterval配置文件0清理任務(wù)TimeTask的執(zhí)行周期,即幾小時(shí)執(zhí)行一次,單位:小時(shí),若設(shè)置為<=0的值,則不會(huì)設(shè)置定時(shí)任務(wù),默認(rèn)不設(shè)置.

思考

配置項(xiàng)中只有snapRetainCount用于設(shè)置清理后保留的快照文件個(gè)數(shù),那清理快照文件時(shí)會(huì)同時(shí)清理事務(wù)日志文件嗎?若會(huì)清理,清理之后會(huì)保留幾個(gè)事務(wù)日志文件呢?

答案:清理快照文件時(shí)會(huì)同時(shí)清理事務(wù)日志文件,假如保留了3個(gè)快照文件,其后綴名分別為100,200,300,則若事務(wù)日志文件中包含事務(wù)id>100的事務(wù),則該事務(wù)日志文件被保留.則事務(wù)日志文件后綴>100的都會(huì)被保留,此外,后綴名<=100的事務(wù)日志文件中最新的事務(wù)日志也被保留.因?yàn)榧词乖撌聞?wù)日志文件后綴<=100,但是可能其包含的事務(wù)中一部分id<=100,一部分>100,此時(shí)也需保留該文件
事務(wù)日志和快照文件后綴名的含義見Zookeeper-持久化

創(chuàng)建ZooKeeper數(shù)據(jù)管理器

即初始化FileTxnSnapLog,FileTxnSnapLog組合了TxnLogSnapShot,根據(jù)類名也可以看出,TxnLog負(fù)責(zé)處理事務(wù)日志,SnapShot負(fù)責(zé)處理快照.FileTxnSnapLog是Zookeeper上層服務(wù)器和底層數(shù)據(jù)存儲(chǔ)之間的對(duì)接層,提供一系列操作數(shù)據(jù)文件的方法,如:

  1. restore(DataTree, Map, PlayBackListener)
    啟動(dòng)ZookeeperServer時(shí)調(diào)用此方法從磁盤上的快照和事務(wù)日志中恢復(fù)數(shù)據(jù)

  2. getLastLoggedZxid()
    獲取日志中記載的最新的zxid

  3. save(DataTree,ConcurrentHashMap, boolean syncSnap)
    將內(nèi)存中的數(shù)據(jù)持久化到磁盤中

除此之外還有大量方法便于操作快照和事務(wù)日志.

注冊(cè)shutdownhandler

在服務(wù)器單機(jī)啟動(dòng)結(jié)束后有一句shutdownLatch.await(),服務(wù)器運(yùn)行到此已經(jīng)啟動(dòng)完畢,主線程阻塞在此處.但服務(wù)器退出時(shí)還需要做一些清理工作,因此注冊(cè)shutdownhandler,在ZooKeeperServer#setState(State)中調(diào)用此方法.

/** * 當(dāng)服務(wù)器狀態(tài)變?yōu)閌ERROR`或`SHUTDOWN`時(shí)喚醒shutdownLatch,執(zhí)行后續(xù)的清理代碼. * @param state new server state */void handle(State state) {if (state == State.ERROR || state == State.SHUTDOWN) { shutdownLatch.countDown(); } }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

啟動(dòng)Admin server

AdminServer是3.5.0之后支持的特性,啟動(dòng)了一個(gè)jettyserver,默認(rèn)端口是8080,訪問此端口可以獲取Zookeeper運(yùn)行時(shí)的相關(guān)信息:


如服務(wù)器的相關(guān)配置,統(tǒng)計(jì)信息等.

相關(guān)配置

其配置如下

參數(shù)名默認(rèn)描述
admin.enableServertrue設(shè)置為“false”禁用AdminServer。默認(rèn)情況下,AdminServer是啟用的。對(duì)應(yīng)java系統(tǒng)屬性是:zookeeper.admin.enableServer
admin.serverPort8080Jetty服務(wù)的監(jiān)聽端口,默認(rèn)是8080。對(duì)應(yīng)java系統(tǒng)屬性是:zookeeper.admin.serverPort
admin.commandURL“/commands”訪問路徑

如果在啟動(dòng)Zookeeper時(shí)提示Unable to start AdminServer, exiting abnormally,可能就是tomcat或其他軟件占用了8080端口,需要修改AdminServer的默認(rèn)端口.

創(chuàng)建并啟動(dòng)網(wǎng)絡(luò)IO管理器

ServerCnxnFactory是Zookeeper中的重要組件,負(fù)責(zé)處理客戶端與服務(wù)器的連接.主要有兩個(gè)實(shí)現(xiàn),一個(gè)是NIOServerCnxnFactory,使用Java原生NIO處理網(wǎng)絡(luò)IO事件;另一個(gè)是NettyServerCnxnFactory,使用Netty處理網(wǎng)絡(luò)IO事件.作為處理客戶端連接的組件,其會(huì)啟動(dòng)若干線程監(jiān)聽客戶端連接端口(即默認(rèn)的9876端口).由于此組件非常復(fù)雜,日后單寫一篇博客講解

啟動(dòng)ZooKeeperServer

啟動(dòng)Zookeeper會(huì)完成兩件事情,一是從磁盤上快照和事務(wù)日志文件將數(shù)據(jù)恢復(fù)到內(nèi)存中,二是啟動(dòng)會(huì)話管理器

恢復(fù)數(shù)據(jù)

    /**     * 初始化ZkDatabase     */public void startdata()throws IOException, InterruptedException {//check to see if zkDb is not nullif (zkDb == null) {            zkDb = new ZKDatabase(this.txnLogFactory);        }if (!zkDb.isInitialized()) {//從快照和事務(wù)日志中恢復(fù)數(shù)據(jù)loadData();        }    }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

/** * Restore sessions and data */public void loadData() throws IOException, InterruptedException {if (zkDb.isInitialized()) { setZxid(zkDb.getDataTreeLastProcessedZxid()); } else {//1.由于zkDatabase尚未初始化,進(jìn)入此分支(通過快照和事務(wù)日志恢復(fù)數(shù)據(jù))setZxid(zkDb.loadDataBase()); }// 2.清理過期session,刪除其對(duì)應(yīng)的nodeList<Long> deadSessions = new LinkedList<Long>();for (Long session : zkDb.getSessions()) {if (zkDb.getSessionWithTimeOuts().get(session) == null) { deadSessions.add(session); } }for (long session : deadSessions) {// XXX: Is lastProcessedZxid really the best thing to use?killSession(session, zkDb.getDataTreeLastProcessedZxid()); }// 3.做一次快照takeSnapshot(); }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

啟動(dòng)會(huì)話管理器

在介紹Zookeeper的回話之前,我們先回憶下Http中的會(huì)話.

由于HTTP協(xié)議是無狀態(tài)的協(xié)議,所以服務(wù)端需要記錄用戶的狀態(tài)時(shí),就需要用某種機(jī)制來識(shí)具體的用戶,這個(gè)機(jī)制就是Session.典型的場景比如購物車,當(dāng)你點(diǎn)擊下單按鈕時(shí),由于HTTP協(xié)議無狀態(tài),所以并不知道是哪個(gè)用戶操作的,所以服務(wù)端要為特定的用戶創(chuàng)建了特定的Session,用于標(biāo)識(shí)這個(gè)用戶,并且跟蹤用戶,這樣才知道購物車?yán)锩嬗袔妆緯?。這個(gè)Session是保存在服務(wù)端的,有一個(gè)唯一標(biāo)識(shí)。在服務(wù)端保存Session的方法很多,內(nèi)存、數(shù)據(jù)庫、文件都有。集群的時(shí)候也要考慮Session的轉(zhuǎn)移,在大型的網(wǎng)站,一般會(huì)有專門的Session服務(wù)器集群,用來保存用戶會(huì)話,這個(gè)時(shí)候 Session 信息都是放在內(nèi)存的,使用一些緩存服務(wù)比如Memcached之類的來放 Session。

session是一個(gè)抽象概念,開發(fā)者為了實(shí)現(xiàn)中斷和繼續(xù)等操作,將 user agent 和 server 之間一對(duì)一的交互,抽象為”會(huì)話”,進(jìn)而衍生出”會(huì)話狀態(tài)”,也就是 session 的概念.
而session的實(shí)現(xiàn)一般是在服務(wù)端保存的一個(gè)數(shù)據(jù)結(jié)構(gòu),用來跟蹤用戶的狀態(tài),這個(gè)數(shù)據(jù)可以保存在集群,數(shù)據(jù)庫,文件中,每一個(gè)session都有一個(gè)sessionId用來唯一標(biāo)識(shí)session.客戶端在發(fā)送請(qǐng)求時(shí),將sessionId作為請(qǐng)求參數(shù)發(fā)送給服務(wù)器,服務(wù)器就可根據(jù)sessionId找到保存在服務(wù)器中的session.

由于Zookeeper提供了臨時(shí)節(jié)點(diǎn),Watcher通知等功能.自然需要保存客戶端的狀態(tài),會(huì)話管理器就是Zookeeper中用于管理會(huì)話的組件.由于此組件過于復(fù)雜,單獨(dú)介紹.

初始化zookeeper的請(qǐng)求處理鏈

類比于tomcat,tomcat處理請(qǐng)求時(shí)會(huì)構(gòu)造pipelinevalue,filterfilterChain兩個(gè)攔截過濾器處理請(qǐng)求,便于職責(zé)的解耦.Zookeeper會(huì)構(gòu)造一個(gè)請(qǐng)求處理鏈用于處理客戶端發(fā)送的請(qǐng)求.此組件過于復(fù)雜,單獨(dú)介紹.

注冊(cè)JMX

JMX的全稱為Java Management Extensions. 顧名思義,是管理Java的一種擴(kuò)展。這種機(jī)制可以方便的管理、監(jiān)控正在運(yùn)行中的Java程序。常用于管理線程,內(nèi)存,日志Level,服務(wù)重啟,系統(tǒng)環(huán)境等

Zookeeper內(nèi)部封裝了注冊(cè)JMX的邏輯,JMX注冊(cè)成功后,可以通過visualVM查看和修改運(yùn)行時(shí)屬性.JMX相關(guān)知識(shí)請(qǐng)查閱資料.

創(chuàng)建并啟動(dòng)secureCnxnFactory

個(gè)人推測此組件應(yīng)該和ServerCnxnFactory提供的功能類似,可能增加了認(rèn)證的邏輯,目前沒有在網(wǎng)上關(guān)于此組件源碼的資料,有時(shí)間查看源碼后補(bǔ)充.

創(chuàng)建并啟動(dòng)ContainerManager

容器節(jié)點(diǎn)

Zookeeper中的節(jié)點(diǎn)類型有持久節(jié)點(diǎn),持久順序節(jié)點(diǎn),臨時(shí)節(jié)點(diǎn),臨時(shí)順序節(jié)點(diǎn),通過創(chuàng)建臨時(shí)順序節(jié)點(diǎn),我們可以實(shí)現(xiàn)leader選舉,分布式鎖等功能,比如實(shí)現(xiàn)一個(gè)分布式鎖,我們的思路一般如下:

  1. 創(chuàng)建一個(gè)持久節(jié)點(diǎn),如”/lock”

  2. 每一個(gè)想獲取鎖的進(jìn)程在該節(jié)點(diǎn)下創(chuàng)建子節(jié)點(diǎn),子節(jié)點(diǎn)類型為臨時(shí)順序節(jié)點(diǎn)

  3. 創(chuàng)建了若干臨時(shí)順序節(jié)點(diǎn)中順序號(hào)最小的節(jié)點(diǎn)的線程獲得鎖;若進(jìn)程未獲得鎖,則在順序號(hào)最小的節(jié)點(diǎn)上注冊(cè)監(jiān)聽事件,監(jiān)聽事件中包括競爭鎖的相關(guān)邏輯.當(dāng)獲取鎖的進(jìn)程釋放鎖(即刪除順序號(hào)最小的節(jié)點(diǎn))時(shí)將回調(diào)監(jiān)聽事件競爭鎖.(簡單介紹分布式鎖的實(shí)現(xiàn)思路,未解決羊群效應(yīng))

問題出現(xiàn)在第一步,為了實(shí)現(xiàn)分布式鎖的邏輯,我們必須建立一個(gè)父節(jié)點(diǎn),且其類型為持久節(jié)點(diǎn),但是當(dāng)不需要分布式鎖時(shí)誰來刪除/lock節(jié)點(diǎn)呢?
為了解決這個(gè)問題,Zookeeper在3.6.0版本新增一種節(jié)點(diǎn)類型,即容器節(jié)點(diǎn).其特點(diǎn)為:當(dāng)容器節(jié)點(diǎn)的最后一個(gè)孩子節(jié)點(diǎn)被刪除之后,容器節(jié)點(diǎn)將被標(biāo)注并在一段時(shí)間后刪除.
那么在實(shí)現(xiàn)分布式鎖時(shí),可以將/lock類型設(shè)置為容器節(jié)點(diǎn),當(dāng)沒有線程競爭分布式鎖時(shí),/lock節(jié)點(diǎn)會(huì)被Zookeeper自動(dòng)刪除.

屬性

ContainerManager中有兩個(gè)重要參數(shù)控制其行為:

屬性名對(duì)應(yīng)配置配置方式默認(rèn)值含義
checkIntervalMsznode.container.checkIntervalMs系統(tǒng)屬性60_000執(zhí)行兩次檢查任務(wù)之間的時(shí)間間隔,單位:ms,默認(rèn)1min
maxPerMinuteznode.container.maxPerMinute系統(tǒng)屬性10_000一分鐘內(nèi)最多刪除多少個(gè)容器節(jié)點(diǎn),即刪除兩個(gè)容器節(jié)點(diǎn)之間的最少時(shí)間間隔為60000/10000=6ms

注:上述屬性通過設(shè)置系統(tǒng)屬性配置,即在啟動(dòng)QuorumPeerMain時(shí)添加-Dznode.container.checkIntervalMs=XXX

實(shí)現(xiàn)

為了能夠及時(shí)清理容器節(jié)點(diǎn),通過Timer來執(zhí)行定時(shí)任務(wù),實(shí)現(xiàn)代碼如下:

    /**     * Manually check the containers. Not normally used directly     */public void checkContainers()throws InterruptedException {//刪除兩個(gè)容器節(jié)點(diǎn)之間的最小間隔,默認(rèn):6mslong minIntervalMs = getMinIntervalMs();//遍歷待刪除的容器節(jié)點(diǎn)(同時(shí)會(huì)刪除過期的TTL節(jié)點(diǎn))for (String containerPath : getCandidates()) {long startMs = Time.currentElapsedTime();            ByteBuffer path = ByteBuffer.wrap(containerPath.getBytes());            Request request = new Request(null, 0, 0,                    ZooDefs.OpCode.deleteContainer, path, null);try {                LOG.info('Attempting to delete candidate container: {}',                        containerPath);//只是將刪除節(jié)點(diǎn)的請(qǐng)求發(fā)送給PrepRequestProcessor,并未真正刪除該節(jié)點(diǎn)requestProcessor.processRequest(request);            } catch (Exception e) {                LOG.error('Could not delete container: {}',                        containerPath, e);            }//刪除一個(gè)容器節(jié)點(diǎn)所需時(shí)間long elapsedMs = Time.currentElapsedTime() - startMs;long waitMs = minIntervalMs - elapsedMs;//若刪除一個(gè)容器節(jié)點(diǎn)所需時(shí)間小于minIntervalMs,線程sleep.// 由于Timer內(nèi)部只有一個(gè)線程,因此可以保證刪除兩個(gè)容器節(jié)點(diǎn)之間的時(shí)間間隔至少是minIntervalMsif (waitMs > 0) {                Thread.sleep(waitMs);            }        }    }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

總結(jié)

作為一個(gè)服務(wù)器,除了在主線程中進(jìn)行初始化工作,還會(huì)開啟若干線程,為客戶端提供服務(wù),在這里,我們總結(jié)下Zookeeper單機(jī)啟動(dòng)時(shí)啟動(dòng)了多少線程:

  1. 歷史文件清理線程:通過Timer定時(shí)執(zhí)行,執(zhí)行周期為小時(shí)級(jí)別

  2. Admin server:通過內(nèi)置的jetty監(jiān)聽8080端口,但由于對(duì)jetty不了解,不知一共啟動(dòng)了多少個(gè)線程

  3. ServerCnxnFactory:此組件負(fù)責(zé)管理客戶端的TCP連接,其有兩種實(shí)現(xiàn),分別是原生NIO和基于Netty的實(shí)現(xiàn)

  4. 會(huì)話管理器:啟動(dòng)若干線程

  5. 請(qǐng)求處理鏈:啟動(dòng)若干線程

  6. SecureServerCnxnFactory:與ServerCnxnFactory類似

  7. ContainerManager:通過Timer定時(shí)執(zhí)行,清理過期的容器節(jié)點(diǎn)和TTL節(jié)點(diǎn),執(zhí)行周期為分鐘級(jí)別

可以看出,有很多啟動(dòng)線程的組件在此都未做介紹,正式因?yàn)閱?dòng)線程的組件是服務(wù)器的重點(diǎn),內(nèi)容繁多,另開博客介紹

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
分析Zookeeper的一致性原理
【附源碼】Spring Boot微信點(diǎn)餐系統(tǒng),面試可以拿來吹了
Zookeeper源碼
分布式鎖如何實(shí)現(xiàn)
分布式鎖用Redis還是Zookeeper?
ZOOKEEPR的通信架構(gòu)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服