Zookeeper 源码分析-启动

博客分类:

 

本文主要介绍了zookeeper启动的过程

运行zkServer.sh start命令可以启动zookeeper。入口的main函数在类中QuorumPeerMain。

main函数主要调用了runFromConfig函数,创建了QuorumPeer对象,并且调用了start函数,从而启动了zookeeper。

  1. public class QuorumPeerMain {
  2. protected QuorumPeer quorumPeer;
  3. /**
  4. * To start the replicated server specify the configuration file name on
  5. * the command line.
  6. * @param args path to the configfile
  7. */
  8. public static void main(String[] args) {
  9. QuorumPeerMain main = new QuorumPeerMain();
  10. main.initializeAndRun(args);
  11. }
  12. protected void initializeAndRun(String[] args)
  13. throws ConfigException, IOException
  14. {
  15. runFromConfig(config);
  16. }
  17. public void runFromConfig(QuorumPeerConfig config) throws IOException {
  18. LOG.info("Starting quorum peer");
  19. try {
  20. NIOServerCnxn.Factory cnxnFactory =
  21. new NIOServerCnxn.Factory(config.getClientPortAddress(),
  22. config.getMaxClientCnxns());
  23. quorumPeer = new QuorumPeer();
  24. quorumPeer.setClientPortAddress(config.getClientPortAddress());
  25. quorumPeer.setTxnFactory(new FileTxnSnapLog(
  26. new File(config.getDataLogDir()),
  27. new File(config.getDataDir())));
  28. quorumPeer.setQuorumPeers(config.getServers());
  29. quorumPeer.setElectionType(config.getElectionAlg());
  30. quorumPeer.setMyid(config.getServerId());
  31. quorumPeer.setTickTime(config.getTickTime());
  32. quorumPeer.setMinSessionTimeout(config.getMinSessionTimeout());
  33. quorumPeer.setMaxSessionTimeout(config.getMaxSessionTimeout());
  34. quorumPeer.setInitLimit(config.getInitLimit());
  35. quorumPeer.setSyncLimit(config.getSyncLimit());
  36. quorumPeer.setQuorumVerifier(config.getQuorumVerifier());
  37. quorumPeer.setCnxnFactory(cnxnFactory);
  38. quorumPeer.setZKDatabase(new ZKDatabase(quorumPeer.getTxnFactory()));
  39. quorumPeer.setLearnerType(config.getPeerType());
  40. quorumPeer.start();
  41. quorumPeer.join();
  42. } catch (InterruptedException e) {
  43. // warn, but generally this is ok
  44. LOG.warn("Quorum Peer interrupted", e);
  45. }
  46. }
  47. }

在QuorumPeer的start函数中,先调用了loadDataBase方法用于恢复数据。启动与client交互的线程,并

  1. @Override
  2. public synchronized void start() {
  3. try {
  4. zkDb.loadDataBase();
  5. } catch(IOException ie) {
  6. LOG.fatal("Unable to load database on disk", ie);
  7. throw new RuntimeException("Unable to run quorum server ", ie);
  8. }
  9. cnxnFactory.start(); //用于处理与client的交互
  10. startLeaderElection();//开始选举算法
  11. super.start();
  12. }

调用loadDatabase从磁盘加载数据到内存

  1. public long loadDataBase() throws IOException {
  2. PlayBackListener listener=new PlayBackListener(){
  3. public void onTxnLoaded(TxnHeader hdr,Record txn){
  4. Request r = new Request(null, 0, hdr.getCxid(),hdr.getType(),
  5. null, null);
  6. r.txn = txn;
  7. r.hdr = hdr;
  8. r.zxid = hdr.getZxid();
  9. addCommittedProposal(r);
  10. }
  11. };
  12. long zxid = snapLog.restore(dataTree,sessionsWithTimeouts,listener);
  13. initialized = true;
  14. return zxid;
  15. }

调用QuorumPeer的run函数,按照peer的state做不同的处理

  1. @Override
  2. public void run() {
  3. setName("QuorumPeer:" + cnxnFactory.getLocalAddress());
  4. try {
  5. /*
  6. * Main loop
  7. */
  8. while (running) {
  9. switch (getPeerState()) {
  10. case LOOKING:
  11. try {
  12. LOG.info("LOOKING");
  13. setCurrentVote(makeLEStrategy().lookForLeader());
  14. } catch (Exception e) {
  15. LOG.warn("Unexpected exception",e);
  16. setPeerState(ServerState.LOOKING);
  17. }
  18. break;
  19. case OBSERVING:
  20. try {
  21. LOG.info("OBSERVING");
  22. setObserver(makeObserver(logFactory));
  23. observer.observeLeader();
  24. } catch (Exception e) {
  25. LOG.warn("Unexpected exception",e );
  26. } finally {
  27. observer.shutdown();
  28. setObserver(null);
  29. setPeerState(ServerState.LOOKING);
  30. }
  31. break;
  32. case FOLLOWING:
  33. try {
  34. LOG.info("FOLLOWING");
  35. setFollower(makeFollower(logFactory));
  36. follower.followLeader();
  37. } catch (Exception e) {
  38. LOG.warn("Unexpected exception",e);
  39. } finally {
  40. follower.shutdown();
  41. setFollower(null);
  42. setPeerState(ServerState.LOOKING);
  43. }
  44. break;
  45. case LEADING:
  46. LOG.info("LEADING");
  47. try {
  48. setLeader(makeLeader(logFactory));
  49. leader.lead();
  50. setLeader(null);
  51. } catch (Exception e) {
  52. LOG.warn("Unexpected exception",e);
  53. } finally {
  54. if (leader != null) {
  55. leader.shutdown("Forcing shutdown");
  56. setLeader(null);
  57. }
  58. setPeerState(ServerState.LOOKING);
  59. }
  60. break;
  61. }
  62. }
  63. }
  64. }
  65. http://blog.csdn.net/xhh198781/article/details/10949697

Zookeeper 源码分析-启动的更多相关文章

  1. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  2. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  3. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  4. Symfony2源码分析——启动过程2

    文章地址:http://www.hcoding.com/?p=46 上一篇分析Symfony2框架源码,探究Symfony2如何完成一个请求的前半部分,前半部分可以理解为Symfony2框架为处理请求 ...

  5. quartz2.x源码分析——启动过程

    title: quartz2.x源码分析--启动过程 date: 2017-04-13 14:59:01 categories: quartz tags: [quartz, 源码分析] --- 先简单 ...

  6. mysql源码分析-启动过程

    mysql源码分析-启动过程 概要 # sql/mysqld.cc, 不包含psi的初始化过程 mysqld_main: // 加载my.cnf和my.cnf.d,还有命令行参数 if (load_d ...

  7. apiserver源码分析——启动流程

    前言 apiserver是k8s控制面的一个组件,在众多组件中唯一一个对接etcd,对外暴露http服务的形式为k8s中各种资源提供增删改查等服务.它是RESTful风格,每个资源的URI都会形如 / ...

  8. storm操作zookeeper源码分析-cluster.clj

    storm操作zookeeper的主要函数都定义在命名空间backtype.storm.cluster中(即cluster.clj文件中).backtype.storm.cluster定义了两个重要p ...

  9. Symfony2源码分析——启动过程1

    本文通过阅读分析Symfony2的源码,了解Symfony2启动过程中完成哪些工作,从阅读源码了解Symfony2框架. Symfony2的核心本质是把Request转换成Response的一个过程. ...

随机推荐

  1. linux命令:rmdir

    1.命令介绍: rmdir只能用来删除空目录,删除某目录时必须对其父目录有读权限. 2.命令选项: rmdir [选项] 目录 3.命令参数: -p --parent 递归删除目录dirname,当子 ...

  2. node 学习笔记

    以下笔记默认安装完成node 及npm 1.安装express 新版本的express-generator已经独立出来,全局安装这个包就ok. npm install express-generato ...

  3. OD调试程序3

    条件跳转指令的图片,作为以后的参考. 载入了reverses.eve程序,F8下去,发现一个跳转,调用了一个函数,致使程序结束.于是我们绕过它,参考上面的 跳转指令图片. 然后继续F8 又会发现一个跳 ...

  4. git回滚

    Git回滚的常用手法 07net01.com 发布于 4小时前 评论 传统VCS的回滚操作 对于版本控制系统VCS来说,回滚这个操作应该是个很普通也是很重要的需求. 如果你是传统VCS,比如SVN或者 ...

  5. 常用的php字符串处理函数

    php常用的字符串处理函数 1.trim():从字符串的两端删除空白字符和其他预定义字符 ltrim():从字符串的左端删除空格和其他预定义字符 rtrim():从字符串的末端开始删除空白字符和其他预 ...

  6. GitHub for Windows

    /*************************************************************************** * GitHub for Windows * ...

  7. Context启动startActivity注意

    intent.setFlags()方法中参数的用例: 很多人使用startActivity时候,会碰到如下的异常:Caused by: android.util.AndroidRuntimeExcep ...

  8. [转载]架构指南 : Java1.7+Eclipse luna + Maven 3.2.5 +spring 4.1.4

    1. 环境配置 a)         Java 1.7 b)         Eclipse luna c)         Maven3.2.5 d)         spring 4.1.4 2. ...

  9. Java-->分割文件

    --> 通过IO 流将一个文件分割成多份 package com.dragon.java.splitfile; import java.io.File; import java.io.FileI ...

  10. dede首页调用栏目内容_{dede:field.content/}首页调用

    如何将已经做成单页的栏目内容调用到首页来. 常用的需要调到首页来的单页内容,比如公司简介.联系我们等内容,我们在首页可能都要进行展现.通过常规的方式,包括查阅dede官方论坛资料,都找不到比较合适的答 ...