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. Ubuntu 修改IP地址网关

    一.使用命令设置Ubuntu IP地址 1.修改配置文件blacklist.conf禁用IPV6 sudo vi /etc/modprobe.d/blacklist.conf 表示用vi编辑器(也可以 ...

  2. 帝国cms缩略图:网站不同地方生成不同的缩略图

    本文转自:http://blog.sina.com.cn/s/blog_4d49ba58010115sd.html 方便网站多地方调用不同尺寸的缩略图. 根据图片源,在网站任意位置生成不同大小的缩略图 ...

  3. android定时更新文件

    static变量在程序退出时不会清空的,除非系统内存不足以运行其他程序,才会清空.给SD卡上的文件过期时间.可以简单的在给文件命名时后面加个创建时间,在下次访问时判断是否需要更新.比如本来文件名是 i ...

  4. Android Packaging Problem

    android Description Resource Path Location Type Error generating final archive: Debug Certificate ex ...

  5. Sed 直接修改文件

    sed最常用的用法莫过于替换文件,然而其默认的模式是直接输出在shell中 sed 's/Old/New/' My_File.txt 如果我们想要sed直接在文件中更改,只需要在sed后面添加 -i ...

  6. 1130-host ... is not allowed to connect to this MySql server 开放mysql远程连接 不使用localhost

    报错:1130-host ... is not allowed to connect to this MySql server 解决方法: 1. 改表法. 可能是你的帐号不允许从远程登陆,只能在loc ...

  7. 143. Reorder List

    Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do thi ...

  8. BUTTON标签和INPUT标签的区别【转】

    一句话概括主题:<button>具有<input type="button" ... >相同的作用但是在可操控性方面更加强大. HTML 4.01规范的Fo ...

  9. ES6 — 字符串String

    ES6对字符串新增了一些函数和操作规范.下面我们来看ES6中对字符串新加的特性. 1.模版字符串 (即用反引号定义的字符串) 传统的字符串拼接通过我们使用'+'号与变量连接.例如: let name= ...

  10. android之官方下拉刷新组件SwipeRefreshLayout

    1.setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener):设置手势滑动监听器. 2.setProgressBackgr ...