最近正在研究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方法

												

zookeeper源码学习一——zookeeper启动的更多相关文章

  1. 菜鸟系列Fabric源码学习 — peer节点启动

    Fabric 1.4 源码分析peer节点启动 peer模块采用cobra库来实现cli命令. Cobra提供简单的接口来创建强大的现代化CLI接口,比如git与go工具.Cobra同时也是一个程序, ...

  2. SpringBoot源码学习系列之启动原理简介

    本博客通过debug方式简单跟一下Springboot application启动的源码,Springboot的启动源码是比较复杂的,本博客只是简单梳理一下源码,浅析其原理 为了方便跟源码,先找个Ap ...

  3. Zookeeper 源码学习(一)环境搭建

    前言 最近准备学习 Zookeeper,想从 Zookeeper 开始逐步深入了解各类中间件,学习分布式计算. 下载源码 执行指令,下载代码: git clone https://github.com ...

  4. ASP.NET Core MVC 源码学习:MVC 启动流程详解

    前言 在 上一篇 文章中,我们学习了 ASP.NET Core MVC 的路由模块,那么在本篇文章中,主要是对 ASP.NET Core MVC 启动流程的一个学习. ASP.NET Core 是新一 ...

  5. zookeeper源码 — 一、单机启动

    zookeeper一般使用命令工具启动,启动主要就是初始化所有组件,让server可以接收并处理来自client的请求.本文主要结构: main入口 配置解析 组件启动 main入口 我们一般使用命令 ...

  6. ABP 框架从源码学习——abp框架启动和结束(1)

       1.abp框架的启动是从Global.asax文件的Application_Start启动的,当然代表Global的application必须从AbpWebApplication继承: publ ...

  7. ThinkPHP5.0源码学习之框架启动流程

    ThinkPHP5框架的启动流程图如下: ThinkPHP5的启动流程按照文件分为三步: 1.请求入口(public/index.php) 2.框架启动(thinkphp/start.php) 3.应 ...

  8. 菜鸟系列Fabric源码学习—orderer服务启动

    Fabric 1.4 orderer 服务启动流程 1.提要 orderer提供broadcast和deliver两个服务接口.orderer节点与各个peer节点通过grpc连接,orderer将所 ...

  9. ABP 框架从源码学习——abp框架启动核心类AbpBootstrapper(2)

    在AbpBootstrapper中的两个至关重要的属性:IIocManager 和 IAbpModuleManager  public class AbpBootstrapper : IDisposa ...

随机推荐

  1. 学习php前需要了解的知识

    1.静态网站与动态网站 A)静态网站: 不支持数据交互的网站(后缀:   .html  .htm) B)动态网站: 支持数据交互的网站,动态网站可以放静态网页的 i.实现动态网站的技术 1.Asp   ...

  2. 练手CF3-C - Wormhouse

    深搜,亮点在那个剪枝,flag代表是否搜索数组从开始到当前一直等于原始数组同位置的数,如果是真,就从原始数组的当前位置的书开始搜,否则就从0开始搜. 见代码. #include <iostrea ...

  3. HDU 1622

    http://acm.hdu.edu.cn/showproblem.php?pid=1622 白书上6.3.2二叉树层次遍历的例题,层次遍历用bfs,建立二叉树,很基础的题目 #include < ...

  4. javascript:;与javascript:void(0)使用介绍

    有时候我们在编写js过程中,需要触发事件而不需要返回值,那么就可能需要这样的写法 href=”#”,包含了一个位置信息.默认的锚是#top,也就是网页的上端,当连续快速点击此链接时会导致浏览器巨慢甚至 ...

  5. FSM

    一.状态机简单介绍 软件设计中的状态机概念,一般是指有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和 ...

  6. ASP.NET定制简单的错误处理页面

    通常Web应用程序在发布后,为了给用户一个友好界面和使用体验,都会在错误发生时跳转至一个自定义的错误页面,而不是ASP.net向用户暴露出来的详细的异常列表. 简单的错误处理页面可以通过web.con ...

  7. Openstack学习历程_1_视频

    学习视频:讲解Openstack每个模块对应的作用

  8. Ubuntu sudo NOPASSWD设置

    1.首先查看目标用户的信息,包括所属组: ◄► id cason uid=(cason) gid=(cason) (cason),(adm),(cdrom),((dip),(plugdev),(lpa ...

  9. Core Java Volume I — 3.6. Strings

    3.6. StringsConceptually, Java strings are sequences of Unicode characters(Java的字符串是一个Unicode序列). Fo ...

  10. ZOJ 1002 Fire Net

    题目大意:有一个4*4的城市,其中一些格子有墙(X表示墙),在剩余的区域放置碉堡.子弹不能穿透墙壁.问最多可以放置几个碉堡,保证它们不会相互误伤. 解法:从左上的顶点开始遍历,如果这个点不是墙,做深度 ...