QuorumPeerMain-main方法
预启动流程
public static void main(String[] args) {
//创建当前类的对象 就是一个无参构造
QuorumPeerMain main = new QuorumPeerMain();
try {
//调用当前类的初始化与run方法-这个方法才是重点
main.initializeAndRun(args);
...
QuorumPeerMain- initializeAndRun
protected void initializeAndRun(String[] args)
throws ConfigException, IOException, AdminServerException
{ //创建配置对象
QuorumPeerConfig config = new QuorumPeerConfig();
//判断长度是否为1,默认就是zoo.cfg
if (args.length == 1) {
//开始解析
config.parse(args[0]);
}
//历史文件清理管理器-启动任务
// Start and schedule the the purge task
DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config
.getDataDir(), config.getDataLogDir(), config
.getSnapRetainCount(), config.getPurgeInterval());
//开始启动
purgeMgr.start();
//当配置了多个节点时,config.isDistributed==true
if (args.length == 1 && config.isDistributed()) {
//集群模式
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
//单机模式
ZooKeeperServerMain.main(args);
}
}
初始化流程 ZooKeeperServerMain.main(args);
ZooKeeperServerMain.main(args);
public static void main(String[] args) {
QuorumPeerMain main = new QuorumPeerMain();
try {
//初始化
main.initializeAndRun(args);
initializeAndRun
protected void initializeAndRun(String[] args)
throws ConfigException, IOException, AdminServerException
{
try {
//注册日志
ManagedUtil.registerLog4jMBeans();
} catch (JMException e) {
LOG.warn("Unable to register log4j JMX control", e);
}
//创建Server配置对象
ServerConfig config = new ServerConfig();
//只有一个参数
if (args.length == 1) {
//解析配置文件zoo.cfg-并且把解析后的内容,封装到ServerConfig
config.parse(args[0]);
} else {
//多个参数
config.parse(args);
}
//根据配置信息,运行服务
runFromConfig(config);
}
runFromConfig
public void runFromConfig(ServerConfig config)
throws IOException, AdminServerException {
LOG.info("===Starting server===");
//创建事务数据文件快照
FileTxnSnapLog txnLog = null;
try {
// Note that this thread isn't going to be doing anything else,
// so rather than spawning another thread, we will just call
// run() in this thread.
// create a file logger url from the command line args
txnLog = new FileTxnSnapLog(config.dataLogDir, config.dataDir);
//初始化ZooKeeperServer
final ZooKeeperServer zkServer = new ZooKeeperServer(txnLog,
config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, null);
txnLog.setServerStats(zkServer.serverStats());
// Registers shutdown handler which will be used to know the
// server error or shutdown state changes.
final CountDownLatch shutdownLatch = new CountDownLatch(1);
//注册服务器 错误或者关闭 构子 解除shutdownLatch的等待
zkServer.registerServerShutdownHandler(
new ZooKeeperServerShutdownHandler(shutdownLatch));
//创建adminServer
// Start Admin server
adminServer = AdminServerFactory.createAdminServer();
adminServer.setZooKeeperServer(zkServer);
//启动服务 jetty 默认8080 ,可以获取zookeeper运行进的状态数据
adminServer.start();
boolean needStartZKServer = true;
//判断配置文件中的clientPort 2181之类 是否为空
if (config.getClientPortAddress() != null) {
//创建cnxnFactory对象,主要负责,客户端与服务端的连接
cnxnFactory = ServerCnxnFactory.createFactory();
//初始化配置信息 NIO
cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), false);
//启动服务, ServerCnxnFactory ,同时还会启动zookeeeper
cnxnFactory.startup(zkServer);
// zkServer has been started. So we don't need to start it again in secureCnxnFactory.
needStartZKServer = false;
}
//安全模式
if (config.getSecureClientPortAddress() != null) {
secureCnxnFactory = ServerCnxnFactory.createFactory();
secureCnxnFactory.configure(config.getSecureClientPortAddress(), config.getMaxClientCnxns(), true);
secureCnxnFactory.startup(zkServer, needStartZKServer);
}
//容器管理器,定时检查container的节点,判断没有子节点时,删除,周期检查工作
containerManager = new ContainerManager(zkServer.getZKDatabase(), zkServer.firstProcessor,
Integer.getInteger("znode.container.checkIntervalMs", (int) TimeUnit.MINUTES.toMillis(1)),
Integer.getInteger("znode.container.maxPerMinute", 10000)
);
containerManager.start();
// Watch status of ZooKeeper server. It will do a graceful shutdown
// if the server is not running or hits an internal error.
//线程阻塞
shutdownLatch.await();
//一旦上面执行就会关闭服务
shutdown();
if (cnxnFactory != null) {
cnxnFactory.join();
}
if (secureCnxnFactory != null) {
secureCnxnFactory.join();
}
if (zkServer.canShutdown()) {
zkServer.shutdown(true);
}
} catch (InterruptedException e) {
// warn, but generally this is ok
LOG.warn("Server interrupted", e);
} finally {
if (txnLog != null) {
txnLog.close();
}
}
}
ServerCnxnFactory-startup方法
public void startup(ZooKeeperServer zkServer) throws IOException, InterruptedException {
startup(zkServer, true);
}
NIOServerCnxnFactory
@Override
public void startup(ZooKeeperServer zks, boolean startServer)
throws IOException, InterruptedException {
//启动相关线程
start();
//设置
setZooKeeperServer(zks);
//启动服务
if (startServer) {
//加载数据到到zkDatabase
zks.startdata();
//启动定时清理Session管理器,注册JMX,添加处理器
zks.startup();
}
}
@Override
public void start() {
stopped = false;
//wordk线程池
if (workerPool == null) {
workerPool = new WorkerService(
"NIOWorker", numWorkerThreads, false);
}
//循环启动Selector,接收客户连接的
for(SelectorThread thread : selectorThreads) {
if (thread.getState() == Thread.State.NEW) {
thread.start();
}
}
//处理连接进行事件
// ensure thread is started once and only once
if (acceptThread.getState() == Thread.State.NEW) {
acceptThread.start();
}
//处理过期连接
if (expirerThread.getState() == Thread.State.NEW) {
expirerThread.start();
}
}
zks.startdata()
public void startdata()
throws IOException, InterruptedException {
//check to see if zkDb is not null
if (zkDb == null) {
//初始化ZKDatabase 加载原始节点zookeeper
zkDb = new ZKDatabase(this.txnLogFactory);
}
//加载磁盘上的数据,如果有的话
if (!zkDb.isInitialized()) {
//加载数据
loadData();
}
}
zks.startup()
public synchronized void startup() {
if (sessionTracker == null) {
//Session管理器
createSessionTracker();
}
//启动Session管理器
startSessionTracker();
//建立请求处理器
setupRequestProcessors();
//注册jmx
registerJMX();
//设置状态
setState(State.RUNNING);
notifyAll();
}