今天主要是说源码的分析,客户端启动过程的源码分析和服务端启动过程的源码分析。最后在说说zookeeper的运维和总结。源码:https://github.com/limingios/netFuture/源码/『互联网架构』软件架构-zookeeper之源码分析和运维总结(37)

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper

(一)服务的启动过程

  • 初始化

server1,server2,server3,不知道那个是leader,那个是follower,启动完成

『互联网架构』软件架构-zookeeper之源码分析和运维总结_其他_02

  • 选举算法

选择出来leader,follower和observer

『互联网架构』软件架构-zookeeper之源码分析和运维总结_其他_03

如何选举出来的,两种方式
1.jps查看

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_04

2.vim zkServer.sh
『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_05

为了保证写操作的一致性与可用性。
zookeeper专门设计了一种名为原子广播(ZAB)的支持崩溃恢复的一致性协议,基于该协议,zookeeper实现了一种主从模式的系统架构来保持集群中各个副本之间的数据一致性
根据ZAB协议,所有的写操作都必须通过Leader完成,Leader写入本地日常后再复制到所有的Follower节点。
一旦Leader节点无法工作,ZAB协议能够自动从Follower节点中重新选出一个合适的替代者,即新的Leader,该过程即为领导选举,该领导选举过程,是ZAB协议中最为重要和复杂的过程。FastLeaderElection是Fast Paxos算法实现。

3.查看QuorumPeerMain
『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_06

QuorumPeerConfig调用这个方法的parse方法

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_07

加载配置文件FileInputStream,load

『互联网架构』软件架构-zookeeper之源码分析和运维总结_其他_08

load 加载load0

『互联网架构』软件架构-zookeeper之源码分析和运维总结_ide_09

在家配置文件的时候,parseProperties,看到里面获取的关键字,是不是有点惊喜,是不是对应咱们的zoo.cfg文件,获取到之后给属性赋值。

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_10

『互联网架构』软件架构-zookeeper之源码分析和运维总结_其他_11

主类的start方法

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_12

1.loadDataBase 启动时先从内存数据库中恢复数据
2.cnxnFactrory.start() 通过NIO的方式读和写的操作,启动socker编程
3.startLeaderElection 选举算法,选择出来的leader

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_13

4.涉及到的算法,zab和Paxos算法,zab是实践算法(依赖了Paxos的思想做了简化),Paxos属于理论的算法(美国总统竞选的一个过程)。具体Paxos理论:参考源码:里面的文档。start 就是启动开始干活了。

  • 写操作
    1.客户端想Leader发起写请求
    2.Leader将写请求以Proposal(建议)的形式发给所有
    3.Follower并等待ACK(确认)Follower收到Leader的Proposal后返回的ACK
    4.Leader得到过办数的ACK(Leader对自己默认有一个ACK)后向所有的Follower和Observer发送Commint
    5.Leader将处理结果返回给客户端

注意
Leader 不需要得到所有Follower的ACK,只要收到过半的ACK即可,同时Leader本身对自己有的一个ACK Observer虽然没有投票权,但仍须同步Leader的数据从而在处理读请求时,可以返回竟可能新的数据。

『互联网架构』软件架构-zookeeper之源码分析和运维总结_ide_14

默认的没有observer 如何设置
在zoo.cfg中选择一个节点后面添加:obServer

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_15

『互联网架构』软件架构-zookeeper之源码分析和运维总结_ide_16

既然obServer没有投票权,在实际使用中,如果机器比较多允许的话,建议增加一个obServer,不进行投票减少资源的消耗,还能负载减轻其他机器的压力。这就是古代皇宫的太监,能干活还放心,没有话语权,只会干活。

(二)客户的启动过程

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_17

  • 客户端的启动流程
public ZooKeeper(String connectString,  int sessionTimeout, Watcher watcher,boolean canBeReadOnly) throws IOException
{
LOG .info( "Initiating client connection, connectString=" + connectString
+  " sessionTimeout=" + sessionTimeout +  " watcher=" + watcher);
watchManager. defaultWatcher = watcher;

ConnectStringParser connectStringParser =  new ConnectStringParser(
connectString);

HostProvider hostProvider =  new StaticHostProvider(
connectStringParser.getServerAddresses());//拿到 ip 端口号

cnxn =  new ClientCnxn(connectStringParser.getChrootPath(),
hostProvider, sessionTimeout,  this,  watchManager,
getClientCnxnSocket (), canBeReadOnly);//创建 ClientCnxn 对象

cnxn.start();//非 thread 线程启动
}
  • org.apache.zookeeper.ClientCnxn#ClientCnxn 初始化 启动了两个线程 send 和 event
public ClientCnxn(String chrootPath, HostProvider hostProvider,  int
sessionTimeout, ZooKeeper zooKeeper,ClientWatchManager watcher, ClientCnxnSocket clientCnxnSocket,long sessionId,  byte[] sessionPasswd,  boolean canBeReadOnly) {
  this. zooKeeper = zooKeeper;
  this. watcher = watcher;
  this. sessionId = sessionId;
  this. sessionPasswd = sessionPasswd;
  this. sessionTimeout = sessionTimeout;
  this. hostProvider = hostProvider;
  this. chrootPath = chrootPath;
  connectTimeout = sessionTimeout / hostProvider.size();
  readTimeout = sessionTimeout * 2 / 3;
  readOnly = canBeReadOnly;
  sendThread =  new SendThread(clientCnxnSocket);
  eventThread =  new EventThread();
}
  • 队列包括3个队列

outgoingQueue,该队列用于存放等待发送的数据包。
pendingQueue,该队列用于存放已发送,等待服务端响应的数据包。
waitingEvents,服务端的响应会封装成事件放入该队列中等待处理。

用户发送一个读取数据节点的请求,该请求首先被封装成一个相应类型的数据包放入outgoingQueue队列中,sendThread会把数据包从队列中取出然后发往服务端并把该数据包加入到pendingQueue中,当sendThread收到服务端响应时,会与pendingQueue队列中的第一个数据包进行对比,判断是否是期待的那个响应包(这里可以看出数据包是串行处理的),最后把响应的数据包封装成对应类型的事件加入到waitingEvents中,再由eventThread取出进行处理。

(三)运维相关

  • 阿里云zookeeper界面工具

官网地址:https://github.com/alibaba/taokeeper/downloads
因为太久没更新了,了解下就可以了不建议使用

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_18

  • zkweb

zookeeper web管理和监控界面,使用内置的H2数据库,此版本基于淘宝大神yasenagat的zkWeb源码基础之上进行了大幅升级和修改,主要新增了集群监控和国际化功能,直接java -jar或将war包放入tomcat即可运行!
官网地址:https://github.com/zhitom/zkweb

『互联网架构』软件架构-zookeeper之源码分析和运维总结_ide_19

  • 运维常用命令

输出server的详细配置信息

echo conf|nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_20

输出指定server上所有客户端连接的详细信息,包括客户端IP,会话ID等
连接信息的总览,连接ip、端口号、该连接的发包数、该连接的收包数、连接的session Id、最后操作方式/命令、连接的时间戳、超时时间(未确认)、最后的zxid、最后、响应时间戳、连接的时间延时信息等

echo cons|nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_其他_21

功能性命令。重置所有连接的统计信息

echo crst|nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_ide_22

针对Leader执行,用于输出所有等待队列中的会话和临时节点的信息

echo dump|nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_ide_23

输出server简要状态和连接的客户端信息

echo stat|nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_24

列出所有watcher信息,以watcher的session为归组单元排列,列出该会话订阅了哪些path。

echo wchc|nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_25

输出一些ZK运行时信息
版本、延时、收包、发包、连接数、未完成客户端请求数、leader/follower 状态、znode 数、watch 数、临时节点数、近似数据大小 应该是一个总和的值、打开文件描述符 数、最大文件描述符数、fllower数等等

echo mntr | nc localhost 2181

『互联网架构』软件架构-zookeeper之源码分析和运维总结_客户端_26

『互联网架构』软件架构-zookeeper之源码分析和运维总结_zookeeper_27

PS:zookeeper就告一段落了,zookeeper互联网的奠基石,这个一定要理解原理,有基本的使用,架构之路必须要翻越的一面墙