客户端
我们都知道Zookeeper的客户端的启动命令如下
./zkCli.sh -server localhost:2182
所以关键就是zkCli.sh这个脚本文件
打开之后我们发现其实这个脚本就是执行了ZooKeeperMain的main
方法,所以我们来到源码中,基本流程见注释
public static void main(String args[])
throws KeeperException, IOException, InterruptedException
{
/**
* 主要是创建了一个原生的zookeeper的客户端,其实是一个ClientCnxn对象
* 底层是初始化并启动了两个线程,分别是
* 1.sendThread
* 2.eventThread
*
* sendTread的基本流程
* sendThread的作用主要是于服务端建立socket连接(NIOsocket)
* 将之前封装的packet加到outgoingQueue中
* 再从outgoingQueue取出packet发送请求,移除outgoingQueue中的packet,并将packet放到一个pendingQueue队列中
* 最后读取响应信息,将响应信息写到packet中去,并通过packet唤醒主线程的阻塞
*
*/
ZooKeeperMain main = new ZooKeeperMain(args);
/**
* 调用run方法
* 这里主要是解析了命令并进行了一些判断异常
* 并且做出了一些命令行的显示
* 最后是调用的原生客户端的方法执行命令
* 原生客户端主要是将命令的一些信息封装成了一个packet对象
* 再通过packet的await方法阻塞住线程
* 当唤醒时packet就会有了响应的信息
* 最后同样会对命令行做会先处理
*/
main.run();
}
客户端流程图如下
单机服务端
我们也知道服务端的启动命令如下
./zkServer.sh start /usr/tool/zookeeper-3.4.14/conf/zoo_3.cfg
所以我们可以打开zkServer.sh文件进行分析,然后发现无论如何都会执行QuorumPeerMain这个对象的main
方法
下面就是服务端的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]);
}
// Start and schedule the the purge task
DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config
.getDataDir(), config.getDataLogDir(), config
.getSnapRetainCount(), config.getPurgeInterval());
purgeMgr.start();
// 这里判断是集群模式还是单机模式
if (args.length == 1 && config.servers.size() > 0) {
// 集群
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);
}
}
服务端接受请求流程
- 创建事务日志
- 快照,DataBase,文件
- 更新内存,操作DataTree
- 返回错误或正确信息
处理器链
- PrepRequestProcessor:接收客户端的请求
- SyncRequestProcessor:持久化数据,同步数据,打快照
- FinalRequestProcessor:发送事件,修改内存,把数据通过nio发送回去
单机模式基本流程如下
源码流程如下