以zk原生客户端为例:
我们在win下启动是从D:\tools\zookeeper\zookeeper-3.4.14\bin下的zkCli.cmd
打开这个脚本,可以看到其实就是运行org.apache.zookeeper.ZooKeeperMain这个类
一、客户端启动阶段
当我们双击zkCli.cmd时,启动的过程中,做了哪些事呢
先概况的说下这个方法执行时做了哪些事情,再看它是如何做的
1、读取配置文件
2、创建了一个NIO的socket连接(不然怎么连接服务端)
3、创建了sendThread 线程并启动(看名字就知道,这个线程主要用来向服务端发送请求)
4、创建了eventThread 线程并启动(看名字就知道,这个线程主要用来处理一些事件)
其实客户端主要也就是这些事情,解析配置,连接服务端,发送请求,接收响应
先看main方法
public static void main(String args[])
throws KeeperException, IOException, InterruptedException
{
ZooKeeperMain main = new ZooKeeperMain(args);//New了一个ZookeeperMain类
main.run();//调用了它的run方法
}
ZooKeeperMain中就做了两步:1创建了ZooKeeperMain对象,2调用了main.run方法
1.1 创建了ZooKeeperMain对象
先看下创建了ZooKeeperMain对象的过程中做了哪些事情
public ZooKeeperMain(String args[]) throws IOException, InterruptedException {
cl.parseOptions(args);//解析配置参数
System.out.println("Connecting to " + cl.getOption("server"));
connectToZK(cl.getOption("server"));//连接服务器
}
- 通过parseOptions解析配置的一些参数,比如服务端的ip端口等,没什么好看的,略过
- 通过connectToZK方法连接服务器,看下如何连接
protected void connectToZK(String newHost) throws InterruptedException, IOException {
if (zk != null && zk.getState().isAlive()) {
zk.close();
}
host = newHost;
boolean readOnly = cl.getOption("readonly") != null;
zk = new ZooKeeper(host,
Integer.parseInt(cl.getOption("timeout")),
new MyWatcher(), readOnly);//使用zk原生方式创建了一个连接
}
也就是说在connectToZK方法中,创建了一个Zookeeper对象
看下创建该对象时做了些什么,下面是其构造函数
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
boolean canBeReadOnly) throws IOException {
watchManager.defaultWatcher = watcher;
ConnectStringParser connectStringParser = new ConnectStringParser(
connectString);
HostProvider hostProvider = new StaticHostProvider(
connectStringParser.getServerAddresses());
cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
hostProvider, sessionTimeout,
this,
watchManager,
getClientCnxnSocket(), //这里创建了一个socket
canBeReadOnly
);//创建了一个客户端上下文
cnxn.start();
}
在ZooKeeper的构造函数中
先调用getClientCnxnSocket方法,创建了一个ClientCnxnSocketNIO(称之为连接对象)
又将连接对象作为参数创建了一个ClientCnxn对象(称之为客户端上下文对象)
先看一下getClientCnxnSocket方法,这里需要注意:如果我们不配置参数的话,默认是以NIO的方式创建ClientCnxnSocketNIO连接对象
private static ClientCnxnSocket getClientCnxnSocket() throws IOException {
String clientCnxnSocketName = System
.getProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET);
if (clientCnxnSocketName == null) {
clientCnxnSocketName = ClientCnxnSocketNIO.class.getName();
}
try {
return (ClientCnxnSocket) Class.forName(clientCnxnSocketName).getDeclaredConstructor()
.newInstance();
} catch (Exception e) {
IOException ioe = new IOExceptio