zookeeper源码分析----节点创建流程
来源:互联网 发布:腾讯微信数据库多大 编辑:程序博客网 时间:2024/06/05 01:54
zookeeper作为一个c/s模式的应用程序,在客户端主要是处理(封装)用户请求,序列化,然后以socket方式发送到服务端,服务端进行反序列化之后处理客户端请求数据。
下面是客户端主要的代码:
ZooKeeperMain:主要是处理zookeeper命令行模式的一些操作,其中,处理创建的部分代码如下:
if (cmd.equals("create") && args.length >= 3) { int first = 0; CreateMode flags = CreateMode.PERSISTENT; if ((args[1].equals("-e") && args[2].equals("-s")) || (args[1]).equals("-s") && (args[2].equals("-e"))) { first+=2; flags = CreateMode.EPHEMERAL_SEQUENTIAL; } else if (args[1].equals("-e")) { first++; flags = CreateMode.EPHEMERAL; } else if (args[1].equals("-s")) { first++; flags = CreateMode.PERSISTENT_SEQUENTIAL; } if (args.length == first + 4) { acl = parseACLs(args[first+3]); } path = args[first + 1]; String newPath = zk.create(path, args[first+2].getBytes(), acl, flags); System.err.println("Created " + newPath); }从代码中可以看出,zookeeper在处理命令行命令的时候create等命令只支持小写。在处理create命令之后,会调用ZooKeeper(java编程时所使用客户端)对象来创建节点,ZooKeeper将创建节点的命令封装成一个CreateRequest(实现Record接口)对象,然后将对象序列化发送至服务端(通过NIO客户端ClientCnxnSocketNIO)。
服务端代码:
ZooKeeperServer:主要处理客户端请求,其中,方法processPacket是将请求数据(ByteBuffer)封装成Request对象,代码如下:
Request si = new Request(cnxn, cnxn.getSessionId(), h.getXid(), h.getType(), incomingBuffer, cnxn.getAuthInfo()); si.setOwner(ServerCnxn.me); submitRequest(si);
该对象提交至PrepRequestProcessor对象中,该对象会提交至队列submittedRequests:
public void processRequest(Request request) { // request.addRQRec(">prep="+zks.outstandingChanges.size()); submittedRequests.add(request); }该对象被实例化为一个独立线程在运行,下面是其中run方法:
public void run() { try { while (true) { Request request = submittedRequests.take(); long traceMask = ZooTrace.CLIENT_REQUEST_TRACE_MASK; if (request.type == OpCode.ping) { traceMask = ZooTrace.CLIENT_PING_TRACE_MASK; } if (LOG.isTraceEnabled()) { ZooTrace.logRequest(LOG, traceMask, 'P', request, ""); } if (Request.requestOfDeath == request) { break; } pRequest(request); } } catch (InterruptedException e) { LOG.error("Unexpected interruption", e); } catch (RequestProcessorException e) { if (e.getCause() instanceof XidRolloverException) { LOG.info(e.getCause().getMessage()); } LOG.error("Unexpected exception", e); } catch (Exception e) { LOG.error("Unexpected exception", e); } LOG.info("PrepRequestProcessor exited loop!"); }
pRequest直接调用方法<span style="font-family: Arial, Helvetica, sans-serif;">pRequest2Txn,</span><span style="font-family: Arial, Helvetica, sans-serif;">pRequest2Txn部分代码如下</span><span style="font-family: Arial, Helvetica, sans-serif;">:</span>
case OpCode.create: zks.sessionTracker.checkSession(request.sessionId, request.getOwner()); CreateRequest createRequest = (CreateRequest)record; if(deserialize) ByteBufferInputStream.byteBuffer2Record(request.request, createRequest); String path = createRequest.getPath(); int lastSlash = path.lastIndexOf('/'); if (lastSlash == -1 || path.indexOf('\0') != -1 || failCreate) { LOG.info("Invalid path " + path + " with session 0x" + Long.toHexString(request.sessionId)); throw new KeeperException.BadArgumentsException(path); } List<ACL> listACL = removeDuplicates(createRequest.getAcl()); if (!fixupACL(request.authInfo, listACL)) { throw new KeeperException.InvalidACLException(path); } String parentPath = path.substring(0, lastSlash); ChangeRecord parentRecord = getRecordForPath(parentPath); checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo); int parentCVersion = parentRecord.stat.getCversion(); CreateMode createMode = CreateMode.fromFlag(createRequest.getFlags()); if (createMode.isSequential()) { path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion); } try { PathUtils.validatePath(path); } catch(IllegalArgumentException ie) { LOG.info("Invalid path " + path + " with session 0x" + Long.toHexString(request.sessionId)); throw new KeeperException.BadArgumentsException(path); } try { if (getRecordForPath(path) != null) { throw new KeeperException.NodeExistsException(path); } } catch (KeeperException.NoNodeException e) { // ignore this one } boolean ephemeralParent = parentRecord.stat.getEphemeralOwner() != 0; if (ephemeralParent) { throw new KeeperException.NoChildrenForEphemeralsException(path); } int newCversion = parentRecord.stat.getCversion()+1; request.txn = new CreateTxn(path, createRequest.getData(), listACL, createMode.isEphemeral(), newCversion); StatPersisted s = new StatPersisted(); if (createMode.isEphemeral()) { s.setEphemeralOwner(request.sessionId); } parentRecord = parentRecord.duplicate(request.hdr.getZxid()); parentRecord.childCount++; parentRecord.stat.setCversion(newCversion); addChangeRecord(parentRecord); addChangeRecord(new ChangeRecord(request.hdr.getZxid(), path, s, 0, listACL)); break;
从以上方法中,可以看出zookeeper对于SEQUENTIAL、EPHEMERAL类型节点的处理,特别是SEQUENTIAL类型的节点,对于path的处理比较明显。
另外,对于EPHEMERAL类型的节点,可以从DataTree.createNode()方法以及PrepRequestProcessor.pRequest2Txn()方法中closeSession看到,当session关闭时,将节点类型为EPHEMERAL的数据移除。
0 0
- zookeeper源码分析----节点创建流程
- Zookeeper源码分析(1)- Zookeeper的启动流程
- Zookeeper源码分析(2)- zookeeper的选举流程
- Zookeeper源码分析(五)-Zookeeper选举实例流程
- 【Zookeeper源码二】Zookeeper 客户端创建连接过程分析
- zookeeper创建临时节点
- zookeeper节点创建
- 分析Storm-zookeeper节点
- Zookeeper源码分析(3)- Leader执行流程
- Zookeeper源码分析(4)- Follower执行流程
- ZooKeeper源码分析:Quorum请求的整个流程
- Zookeeper-会话创建流程
- CloudStack 创建VM 源码流程分析
- CloudStack 创建VM 源码流程分析
- Hadoop0.21.0源码流程分析(2)-主节点接收作业
- Hadoop0.21.0源码流程分析(2)-主节点接收作业
- Hadoop源码流程分析4-Task节点执行任务
- Activiti 流程启动及节点流转源码分析
- 灵犀云智能语音云平台产品白皮书(摘要)
- 自学第三天
- 修改jsp、Java文件不用重启Tomcat服务的方法
- SpringJPA(Hibernate) 处理基于基类的关联关系
- Android进阶_WebView与JS进行交互
- zookeeper源码分析----节点创建流程
- CCClipingNode的使用
- Spring Boot 学习第三步(Spring Data JPA学习汇总)
- Minimum Depth of Binary Tree
- java去除字符串中的空格、回车、换行符、制表符
- selenium面试题
- Git 菜鸟变大神(二) 如何提交文件和历史版本恢复
- lcd驱动。。解决开发板小企鹅logo跑偏问题
- Resharper的使用