zookeeper启动入口

  最近正在研究zookeeper,一些心得记录一下,如有错误,还请大神指正。

zookeeper下载地址:http://zookeeper.apache.org/releases.html,百度一下就能找到,不过还是在这里列一下。

我认为学习一个东西,首先要理出一个头绪,否则感觉无从下手,这里我从启动开始研究,即从zkSever.sh入手。

if [ "x$JMXDISABLE" = "x" ]
then
    echo "JMX enabled by default" >&2
    # for some reason these two options are necessary on jdk6 on Ubuntu
    #   accord to the docs they are not necessary, but otw jconsole cannot
    #   do a local attach
    ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMain"
else
    echo "JMX disabled by user request" >&2
    ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi

  从zkSever.sh可以看出,启动入口在QuorumPeerMain中,源码如下:

  // 入口函数
public static void main(String[] args)
  {
    QuorumPeerMain main = new QuorumPeerMain();
   //...1、启动初始化
      main.initializeAndRun(args);
   // ...
  }

  protected void initializeAndRun(String[] args)
    throws QuorumPeerConfig.ConfigException, IOException
  {
    // 2、加载配置文件
    QuorumPeerConfig config = new QuorumPeerConfig();
    if (args.length == 1) {      // 解析配置文件
      config.parse(args[0]);
    }

    if ((args.length == 1) && (config.servers.size() > 0)) {    // 配置文件的信息加载至QuorumPeer
      runFromConfig(config);
    } else {
      LOG.warn("Either no config or no quorum defined in config, running  in standalone mode");

      ZooKeeperServerMain.main(args);
    }
  }

  public void runFromConfig(QuorumPeerConfig config) throws IOException {
    try {
      ManagedUtil.registerLog4jMBeans();
    } catch (JMException e) {
      LOG.warn("Unable to register log4j JMX control", e);
    }

    LOG.info("Starting quorum peer");
    try {
      NIOServerCnxn.Factory cnxnFactory = new NIOServerCnxn.Factory(config.getClientPortAddress(), config.getMaxClientCnxns());

      // 3、启动QuorumPeer
      this.quorumPeer = new QuorumPeer();
      this.quorumPeer.setClientPortAddress(config.getClientPortAddress());
      //...加载各种配置信息

      this.quorumPeer.start();
      this.quorumPeer.join();
    }
    catch (InterruptedException e) {
      LOG.warn("Quorum Peer interrupted", e);
    }
  }

  可以看出,配置文件的解析由QuorumPeerConfig 类完成,其部分源码如下:

  public void parse(String path)
    throws QuorumPeerConfig.ConfigException
  {
    File configFile = new File(path);

    LOG.info("Reading configuration from: " + configFile);
    try
    {
      if (!configFile.exists()) {
        throw new IllegalArgumentException(configFile.toString() + " file is missing");
      }
     // 将配置信息加载如property文件
      Properties cfg = new Properties();
      FileInputStream in = new FileInputStream(configFile);
      try {
        cfg.load(in);
      } finally {
        in.close();
      }

      parseProperties(cfg);
    } catch (IOException e) {
      throw new ConfigException("Error processing " + path, e);
    } catch (IllegalArgumentException e) {
      throw new ConfigException("Error processing " + path, e);
    }
  }

  public void parseProperties(Properties zkProp)
    throws IOException, QuorumPeerConfig.ConfigException
  {
    int clientPort = 0;
    String clientPortAddress = null;// 循环解析配置文件
    for (Map.Entry entry : zkProp.entrySet()) {
      String key = entry.getKey().toString().trim();
      String value = entry.getValue().toString().trim();
      if (key.equals("dataDir")) {
        this.dataDir = value;
      } else if (key.equals("dataLogDir")) {
        this.dataLogDir = value;
      } else if (key.equals("clientPort")) {    // 客户端连接的端口号
        clientPort = Integer.parseInt(value);
      } else if (key.equals("clientPortAddress")) {
        clientPortAddress = value.trim();
      } else if (key.equals("tickTime")) {    // 心跳时间
        this.tickTime = Integer.parseInt(value);
      } else if (key.equals("maxClientCnxns")) {
        this.maxClientCnxns = Integer.parseInt(value);
      } else if (key.equals("minSessionTimeout")) {
        this.minSessionTimeout = Integer.parseInt(value);
      } else if (key.equals("maxSessionTimeout")) {
        this.maxSessionTimeout = Integer.parseInt(value);
      } else if (key.equals("initLimit")) {
        this.initLimit = Integer.parseInt(value);
      } else if (key.equals("syncLimit")) {
        this.syncLimit = Integer.parseInt(value);
      } else if (key.equals("electionAlg")) {    // 选举算法的类型,默认算法为FastLeaderElection
        this.electionAlg = Integer.parseInt(value);
      } else if (key.equals("peerType")) {
        if (value.toLowerCase().equals("observer"))
          this.peerType = QuorumPeer.LearnerType.OBSERVER;
        else if (value.toLowerCase().equals("participant")) {
          this.peerType = QuorumPeer.LearnerType.PARTICIPANT;
        }
        else
          throw new ConfigException("Unrecognised peertype: " + value);
      }
      //...

  回到QuorumPeerMain类的runFromConfig方法。此方法中,会将配置信息加载至QuorumPeer,并调用其start方法:

  public synchronized void start()
  {
    try {
      this.zkDb.loadDataBase();
    } catch (IOException ie) {
      LOG.fatal("Unable to load database on disk", ie);
      throw new RuntimeException("Unable to run quorum server ", ie);
    }
    this.cnxnFactory.start();
    startLeaderElection();
    super.start();
  }

  在start方法中,会现价在硬盘中的数据,

 this.zkDb.loadDataBase();即ZKDatabase中
  public long loadDataBase()
    throws IOException
  {
    FileTxnSnapLog.PlayBackListener listener = new FileTxnSnapLog.PlayBackListener() {
      public void onTxnLoaded(TxnHeader hdr, Record txn) {
        Request r = new Request(null, 0L, hdr.getCxid(), hdr.getType(), null, null);

        r.txn = txn;
        r.hdr = hdr;
        r.zxid = hdr.getZxid();
        ZKDatabase.this.addCommittedProposal(r);
      }
    };
    long zxid = this.snapLog.restore(this.dataTree, this.sessionsWithTimeouts, listener);
    this.initialized = true;
    return zxid;
  }

  然后开确定选类型,startLeaderElection

  public synchronized void startLeaderElection() {
    this.currentVote = new Vote(this.myid, getLastLoggedZxid());
    for (QuorumServer p : getView().values()) {
      if (p.id == this.myid) {
        this.myQuorumAddr = p.addr;
        break;
      }
    }
    if (this.myQuorumAddr == null) {
      throw new RuntimeException("My id " + this.myid + " not in the peer list");
    }
    if (this.electionType == 0) {
      try {
        this.udpSocket = new DatagramSocket(this.myQuorumAddr.getPort());
        this.responder = new ResponderThread();
        this.responder.start();
      } catch (SocketException e) {
        throw new RuntimeException(e);
      }
    }
    this.electionAlg = createElectionAlgorithm(this.electionType);//加载选举类型}

  然后启动run方法

时间: 2024-12-19 11:24:10

zookeeper启动入口的相关文章

zookeeper启动流程简单梳理

等着测试童鞋完工,顺便里了下zookeeper的启动流程 zk3.4.6 启动脚本里面 nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_D

python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。

本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding:utf-8from com.wenhy.crawler_baidu_baike import url_manager, html_downloader, html_parser, html_outputer print "爬虫百度百科调度入口" # 创建爬虫类class SpiderMai

zookeeper启动报错(数据目录权限不对)

zookeeper启动报错日志: 2016-11-16 11:19:43,880 [myid:3] - INFO [WorkerReceiver[myid=3]:[email protected]] - Notification: 3 (n.leader), 0x200111a88 (n.zxid), 0x1 (n.round), LOOKING (n.state), 3 (n.sid), 0x2 (n.peerEPoch), LOOKING (my state) 2016-11-16 11:1

Angularjs启动入口, splash画面,与加快启动的技巧

Angularjs启动入口 * 自动响应DOMContentLoaded event * 从ngApp指定的入口启动: 在angular.js执行后, 如果 document.readyState是'complete', 则寻找并执行ngApp指定的root *** load它指定的module *** 建立app的injector *** 编译DOM上ngApp指定的部分 (不一定是全部DOM), * 用angular.bootstrap()启动,(不能与 ngApp混用) *** 先load

zookeeper启动失败

集群中3个节点,第一个started,第二个说Starting zookeeper ... already running as process xxxx,第三个说Starting zookeeper ... already running as process yyyy. 原来是相应目录下残留的pid文件导致启动失败,打开那个文件一看里边的进程号正是提示出现的xxxx,yyyy.删除他们后重启,好了. zookeeper启动失败

zookeeper启动异常

zookeeper启动报异常 java.io.EOFException  at java.io.DataInputStream.readInt(DataInputStream.java:392) 遇到这个问题 第一步先删除 缓存文件 打开 conf 文件夹 找到 zoo.cfg 文件 找到缓存数据文件夹 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo } span.s1 { } dataDir=/home349/vlan/zo

SpringBoot(二):设置springboot同一接口程序启动入口

根据上一篇文章中搭建了一个springboot简单工程,在该工程中编写HelloWordController.java接口类,并在该类中写了一个main函数,做为该类的接口服务启动入口.此时如果新增多个接口服务类时,不修改任何代码是无法访问新增类的接口服务. 实际上springboot提供了统一配置全局扫描接口服务类的启动方法,本文就介绍如何使用: 如何配置统一启动入口 在src根目录下新建一个app包,在包下创建一个App.java类,通过代码配置使其作为该工程的一个通用启动入口类: pack

Zookeeper启动失败,报错 can not open chanel to 2

zookeeper 3.4.8 安装在 7 台不同的虚拟机上,配置文件如下: tickTime=2000 initLimit=10 syncLimit=5 dataDir=/var/zookeeper clientPort=2181 server.1=master1:2888:3888 server.2=master2:2888:3888 server.3=slave1:2888:3888 server.4=slave2:2888:3888 server.5=slave3:2888:3888 s

ZooKeeper启动过程2:FastLeaderElection

前一篇文章中说到,启动ZooKeeper集群时,需要分别启动集群中的各个节点,各节点以QuorumPeer的形式启动,最后到达startLeaderElection和lookForLeader. 先说startLeaderElection 首先,初始化节点自身的currentVote[当前投票]为[myid.zxid.currentEpoch] 然后,初始化选举算法createElectionAlgorithm,默认使用FastLeaderElection算法,在这里,启动两个线程WorkerS