Zookeeper源码解析之Server启动
来源:互联网 发布:.sit域名 无法备案 编辑:程序博客网 时间:2024/05/16 18:56
本篇讲述Zookeeper Server启动过程。Zookeeper的源码可以在Github中下载,地址是:https://github.com/apache/zookeeper/。不过是用ivy构建,所以有兴趣的话,可以安装ivy来构建Zookeeper。
Zookeeper的启动类:org.apache.zookeeper.server.quorum.QuorumPeerMain
通过Main函数启动:
public static void main(String[] args) { QuorumPeerMain main = new QuorumPeerMain(); try { //初始化并运行 main.initializeAndRun(args); } catch (IllegalArgumentException e) { LOG.error("Invalid arguments, exiting abnormally", e); LOG.info(USAGE); System.err.println(USAGE); System.exit(2); } catch (ConfigException e) { LOG.error("Invalid config, exiting abnormally", e); System.err.println("Invalid config, exiting abnormally"); System.exit(2); } catch (Exception e) { LOG.error("Unexpected exception, exiting abnormally", e); System.exit(1); } LOG.info("Exiting normally"); System.exit(0); }
初始化并运行:
protected void initializeAndRun(String[] args) throws ConfigException, IOException { //加载配置文件实现类 QuorumPeerConfig config = new QuorumPeerConfig(); if (args.length == 1) { config.parse(args[0]); } //启动并调度清理任务,主要的配置是:autopurge.snapRetainCount(保留日志和快照文件的数量),清理任务的频率:autopurge.purgeInterval(单位:小时) DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config .getDataDir(), config.getDataLogDir(), config .getSnapRetainCount(), config.getPurgeInterval()); purgeMgr.start(); if (args.length == 1 && config.servers.size() > 0) { //根据配置文件运行Zookeeper runFromConfig(config); } else { LOG.warn("Either no config or no quorum defined in config, running " + " in standalone mode"); // there is only server in the quorum -- run as standalone //单机模式下运行Zookeeper ZooKeeperServerMain.main(args); } }
根据配置文件运行:
public void runFromConfig(QuorumPeerConfig config) throws IOException { try { //注册JMX ManagedUtil.registerLog4jMBeans(); } catch (JMException e) { LOG.warn("Unable to register log4j JMX control", e); } LOG.info("Starting quorum peer"); try { ServerCnxnFactory cnxnFactory = ServerCnxnFactory.createFactory(); cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns()); //实例化QuorumPeer quorumPeer = new QuorumPeer(); //服务监听端口 quorumPeer.setClientPortAddress(config.getClientPortAddress()); //日志和快照存放路径 quorumPeer.setTxnFactory(new FileTxnSnapLog( new File(config.getDataLogDir()), new File(config.getDataDir()))); //Server Map quorumPeer.setQuorumPeers(config.getServers()); //选举算法 quorumPeer.setElectionType(config.getElectionAlg()); //服务器ID quorumPeer.setMyid(config.getServerId()); //时间单元 quorumPeer.setTickTime(config.getTickTime()); //最大和最小超时时间 quorumPeer.setMinSessionTimeout(config.getMinSessionTimeout()); quorumPeer.setMaxSessionTimeout(config.getMaxSessionTimeout()); //交互的时间限制 quorumPeer.setInitLimit(config.getInitLimit()); quorumPeer.setSyncLimit(config.getSyncLimit()); quorumPeer.setQuorumVerifier(config.getQuorumVerifier()); //连接工厂,默认NIOServerCnxnFactory quorumPeer.setCnxnFactory(cnxnFactory); quorumPeer.setZKDatabase(new ZKDatabase(quorumPeer.getTxnFactory())); quorumPeer.setLearnerType(config.getPeerType()); quorumPeer.setSyncEnabled(config.getSyncEnabled()); quorumPeer.setQuorumListenOnAllIPs(config.getQuorumListenOnAllIPs()); //启动 quorumPeer.start(); quorumPeer.join(); } catch (InterruptedException e) { // warn, but generally this is ok LOG.warn("Quorum Peer interrupted", e); } }}
启动:
@Override public synchronized void start() { //日志文件和快照文件 loadDataBase(); //启动连接工厂,主要用于处理Client的请求 cnxnFactory.start(); //初始化选举,主要是开始Leader的选举 startLeaderElection(); //启动 super.start(); }
loadDataBase过程,恢复epoch数:
private void loadDataBase() { File updating = new File(getTxnFactory().getSnapDir(), UPDATING_EPOCH_FILENAME);try { //从文件中恢复db zkDb.loadDataBase(); //从最新的zxid恢复epoch变量,zxid64位,前32位是epoch值,后32位是zxid long lastProcessedZxid = zkDb.getDataTree().lastProcessedZxid; long epochOfZxid = ZxidUtils.getEpochFromZxid(lastProcessedZxid); try { currentEpoch = readLongFromFile(CURRENT_EPOCH_FILENAME); if (epochOfZxid > currentEpoch && updating.exists()) { LOG.info("{} found. The server was terminated after " + "taking a snapshot but before updating current " + "epoch. Setting current epoch to {}.", UPDATING_EPOCH_FILENAME, epochOfZxid); setCurrentEpoch(epochOfZxid); if (!updating.delete()) { throw new IOException("Failed to delete " + updating.toString()); } } } catch(FileNotFoundException e) { // pick a reasonable epoch number // this should only happen once when moving to a // new code version currentEpoch = epochOfZxid; LOG.info(CURRENT_EPOCH_FILENAME + " not found! Creating with a reasonable default of {}. This should only happen when you are upgrading your installation", currentEpoch); writeLongToFile(CURRENT_EPOCH_FILENAME, currentEpoch); } if (epochOfZxid > currentEpoch) { throw new IOException("The current epoch, " + ZxidUtils.zxidToString(currentEpoch) + ", is older than the last zxid, " + lastProcessedZxid); } try { acceptedEpoch = readLongFromFile(ACCEPTED_EPOCH_FILENAME); } catch(FileNotFoundException e) { // pick a reasonable epoch number // this should only happen once when moving to a // new code version acceptedEpoch = epochOfZxid; LOG.info(ACCEPTED_EPOCH_FILENAME + " not found! Creating with a reasonable default of {}. This should only happen when you are upgrading your installation", acceptedEpoch); writeLongToFile(ACCEPTED_EPOCH_FILENAME, acceptedEpoch); } if (acceptedEpoch < currentEpoch) { throw new IOException("The current epoch, " + ZxidUtils.zxidToString(currentEpoch) + " is less than the accepted epoch, " + ZxidUtils.zxidToString(acceptedEpoch)); } } catch(IOException ie) { LOG.error("Unable to load database on disk", ie); throw new RuntimeException("Unable to run quorum server ", ie); }}
初始化选举
synchronized public void startLeaderElection() { try { //初始化投票实例,投票的对象是自己 currentVote = new Vote(myid, getLastLoggedZxid(), getCurrentEpoch()); } catch(IOException e) { RuntimeException re = new RuntimeException(e.getMessage()); re.setStackTrace(e.getStackTrace()); throw re; } //从配置中拿自己的选举地址 for (QuorumServer p : getView().values()) { if (p.id == myid) { myQuorumAddr = p.addr; break; } } if (myQuorumAddr == null) { throw new RuntimeException("My id " + myid + " not in the peer list"); } if (electionType == 0) { try { udpSocket = new DatagramSocket(myQuorumAddr.getPort()); responder = new ResponderThread(); responder.start(); } catch (SocketException e) { throw new RuntimeException(e); } } //根据配置文件,初始化选举实例。默认是FastLeaderElection this.electionAlg = createElectionAlgorithm(electionType); }server启动完成,就等待client去连接了。server启动核心功能就是从snapshot和log文件中恢复datatree,其核心就是zxid。
0 0
- Zookeeper源码解析之Server启动
- Zookeeper源码分析之一Server启动
- ZooKeeper源码解析(四):client如何和server连接
- ZooKeeper源码解析(五):server端如何运行
- Zookeeper源码解析——服务端启动流程
- activeMQ源码解析之源码调试启动
- Eureka 源码解析 —— Eureka-Server 启动(一)之 ServerConfig
- Eureka 源码解析 —— Eureka-Server 启动(二)之 EurekaBootStrap
- Hadoop源码解析之ApplicationMaster启动流程
- pomelo源码解析之compnent组件启动
- Flink源码解析之 --- 启动流程
- Android源码解析之应用程序启动进程
- 深入浅出Zookeeper之一Server启动
- # zookeeper 单机版server启动
- ZooKeeper源码解析(一):ZooKeeper概述
- Zookeeper启动之QuorumPeerMain
- Zookeeper启动解析配置文件QuorumPeerConfig
- Zookeeper源码之ZookeeperServer
- 准确率和召回率
- c语言调用dos命令
- 优秀的API(WEB软件)的设计过程
- ofbiz框架入门例子详解(首篇)-------插入篇
- HACMP 6.1 + ORACLE 10G RAC on AIX6.1 安装文档
- Zookeeper源码解析之Server启动
- Win32 Socket编程注意事项
- 生成UUID
- HTML中button标签通过CSS设置样式
- Java基本知识(连载)-分支和循环-1
- 1043. Is It a Binary Search Tree (25)
- dubbo搭建过程记录(适用本人)
- 线程池
- Java之控制反转和依赖注入