监听器触发流程
客户端发送请求
这里是通过getData请求注册一个默认监听器
这里将监听器对象个监听的节点封装起来,并且存放在客户端中,同时也会把监听器的信息封装到request对象中,但是注意这里只是把是否存在监听器发送过去。
public byte[] getData(final String path, Watcher watcher, Stat stat)
throws KeeperException, InterruptedException
{
final String clientPath = path;
PathUtils.validatePath(clientPath);
// the watch contains the un-chroot path
WatchRegistration wcb = null;
// 注册监听器
// 这里会将监听器对象和节点路径封装起来
if (watcher != null) {
wcb = new DataWatchRegistration(watcher, clientPath);
}
final String serverPath = prependChroot(clientPath);
RequestHeader h = new RequestHeader();
h.setType(ZooDefs.OpCode.getData);
GetDataRequest request = new GetDataRequest();
request.setPath(serverPath);
// 这里会将监听器信息放入request中
// 这里只是将是否注册监听器传进去,并没有把监听器对象传进去
request.setWatch(watcher != null);
GetDataResponse response = new GetDataResponse();
// 这个方法就是将请求向服务端发送过去
// 并阻塞等待响应结果
ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
if (r.getErr() != 0) {
throw KeeperException.create(KeeperException.Code.get(r.getErr()),
clientPath);
}
if (stat != null) {
DataTree.copyStat(response.getStat(), stat);
}
// 返回响应结果
return response.getData();
}
服务端接收请求
这里直接从处理器链中分析,至于服务端通过NIO发送请求就不再分析了,可以参考下面的博文
- PrepRequestProcessor
这个处理器并没有处理关于事件逻辑,下面是调用链
1.org.apache.zookeeper.server.RequestProcessor#processRequest
2.java.util.AbstractQueue#add
3.org.apache.zookeeper.server.PrepRequestProcessor#run
4.org.apache.zookeeper.server.PrepRequestProcessor#pRequest
pRequest方法就是这个处理器的真正的处理方法,这里getData请求只是作了ACL安全验证
然后就是进行下一个处理器