最近正在研究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启动入口的更多相关文章

  1. Zookeeper启动过程

    在上一篇,我们了解了zookeeper最基本的配置,也从中了解一些配置的作用,那么这篇文章中,我们将介绍Zookeeper的启动过程,我们在了解启动过程的时候还要回过头看看上一篇中各个配置参数在启动时 ...

  2. zookeeper源码学习一——zookeeper启动

    最近正在研究zookeeper,一些心得记录一下,如有错误,还请大神指正. zookeeper下载地址:http://zookeeper.apache.org/releases.html,百度一下就能 ...

  3. zookeeper启动流程简单梳理

    等着測试童鞋完工,顺便里了下zookeeper的启动流程 zk3.4.6 启动脚本里面 nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_ ...

  4. 服务端相关知识学习(四)之Zookeeper启动过程

    在上一篇,我们了解了zookeeper最基本的配置,也从中了解一些配置的作用,那么这篇文章中,我们将介绍Zookeeper的启动过程,我们在了解启动过程的时候还要回过头看看上一篇中各个配置参数在启动时 ...

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

    zookeeper启动报错日志: 2016-11-16 11:19:43,880 [myid:3] - INFO [WorkerReceiver[myid=3]:FastLeaderElection@ ...

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

    本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...

  7. zookeeper启动异常

    zookeeper启动报异常 java.io.EOFException  at java.io.DataInputStream.readInt(DataInputStream.java:392) 遇到 ...

  8. Zookeeper启动时报8080端口被占用

    zookeeper启动时报8080 端口被占用,导致启动失败.特别是服务器上部署了tomcat服务时需要注意. 通过查看zookeeper的官方文档,发现有3种解决途径: (1)删除jetty. (2 ...

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

    根据上一篇文章中搭建了一个springboot简单工程,在该工程中编写HelloWordController.java接口类,并在该类中写了一个main函数,做为该类的接口服务启动入口.此时如果新增多 ...

随机推荐

  1. Redis - set类型操作

    set类型操作 设置操作:sadd:        sadd key value        给指定的key添加元素,重复返回0表示添加失败. srem:         srem key valu ...

  2. magento -- 添加中国省份列表

    magento本身的数据库里不包含中国的省份信息,你可以执行以下的SQL语句来添加 添加到directory_country_region表 INSERT INTO  `directory_count ...

  3. opencv3.1包安装

    由于之前零零碎碎安装了很多必要的库: 现在只需: (1)下载和解压包 https://github.com/daveselinger/opencv/tree/3.1.0-with-cuda8 这里的分 ...

  4. Gitlab. Disable user creation on welcome page

    Login to your Gitlab > Admin area > settings > Features > remove the check mark "Si ...

  5. LeetCode Rotate List (链表操作)

    题意: 将链表的后面k个剪出来,拼接到前面,比如 1->2->null 变成2->1->null.数字代表一段的意思. 思路: k有3种可能,k>n,k<n,k=n ...

  6. Windows RPC Demo实现

    Windows RPC Demo实现 本文参考并整理以下相关文章 1. <远程过程调用> -百度百科 2. <RPC 编程> -http://www.ibm.com/devel ...

  7. USB协议-检测设备连接与速度

    在USB设备连接时,USB系统能自动检测到这个连接,并识别出其采用的数据传输速率.USB采用在D+或D-线上增加上拉电阻的方法来识别低速和全速设备. USB支持3种类型的传输速率:1.5Mb/s的低速 ...

  8. Java BTrace实战(1)--BTrace的入门和使用

    前言: 对线上的java服务, 往往采用日志进行问题处理和分析. 倘若日志缺乏相关的信息时, 那又该如何处理? 远程调试会影响服务的正常工作, 修改代码重新部署的方案其实时性和灵活性难以保证(线上服务 ...

  9. Mac中Fn键技巧

    此文适用:Mac自带苹果键盘或外接有Fn键的普通键盘 上一页=Fn+⬅️ 下一页=Fn+➡️ 向上卷动=Fn+⬆️ 向下卷动=Fn+⬇️

  10. xctest错误问题解决

    xctest xctest.h file not found(null): Framework not found XCTest 在FrameWork Search Path里增加以下内容$(PLAT ...