Month July 2018

【JVM】JVM系列之JVM体系(一)

一、前言   为什么要学习了解Java虚拟机 1.我们需要更加清楚的了解Java底层是如何运作的,有利于我们更深刻的学习好Java。 2.对我们调试错误提供很宝贵的经验。 3.这是合格的Java程序必须要了解的内容。 基于此,笔者打算出一个Java虚拟机的系列,加深自己对知识点的理解,同时也方便各位有需要的园友。 二、Java虚拟机的定义 Java虚拟机(Java Virtual Machine),简称JVM。当我们说起Java虚拟机时,可能指的是如下三种不同的东西: 1.抽象规范。 2.一个具体的实现。 3.一个运行中的虚拟机实例。 Java虚拟机抽象规范仅仅是一个概念,在《The Java Virtual Machine Specification》中有详细的描述。该规范的实现,可能来自多个提供商,并存在于多个平台上,它或者是全部由软件实现,或者是以硬件和软件相结合的方式来实现。当运行一个Java程序的时候,也就在运行一个Java虚拟机实例。注意,我们所说的Java平台无关性是指class文件的平台无关性,JVM是和平台相关的,不同操作系统对应不同的JVM。 三、Java虚拟机的总体框架图 下图是整个Java虚拟机的总体框架图,之后我们会经常涉及到。 四、Java虚拟机的体系结构 下图表示了Java虚拟机的结构框图,主要描述了JVM子系统和内存区。 五、Java虚拟机各组成部分 5.1 类装载子系统 类装载子系统负责查找并装载类型,Java虚拟机由两种类装载器:启动类装载器(Java虚拟机实现的一部分)和用户自定义类装载器(Java程序的一部分)。类装载子系统负责定位和导入二进制class文件,并且保证导入类的正确性,为类变量分配并初始化内存,以及帮助解析符号引用。类装载器必须严格按照如下顺序进行类的装载。 1) 装载 — 查找并装载类型的二进制数据 2) 连接 — 执行验证,准备,以及解析(可选),连接分为如下三个步骤 验证 — 确保被导入类型的正确性 准备 — 为类变量分配内存,并将其初始化为默认值…

【分布式】Zookeeper与Paxos

一、前言 在学习了Paxos在Chubby中的应用后,接下来学习Paxos在开源软件Zookeeper中的应用。 二、Zookeeper Zookeeper是一个开源的分布式协调服务,其设计目标是将那些复杂的且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一些列简单的接口提供给用户使用。其是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/发布、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。其可以保证如下分布式一致性特性。 ① 顺序一致性,从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到Zookeeper中去。 ② 原子性,所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,即整个集群要么都成功应用了某个事务,要么都没有应用。 ③ 单一视图,无论客户端连接的是哪个Zookeeper服务器,其看到的服务端数据模型都是一致的。 ④ 可靠性,一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直被保留,除非有另一个事务对其进行了变更。 ⑤ 实时性,Zookeeper保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。 2.1 设计目标 Zookeeper致力于提供一个高性能、高可用、且具有严格的顺序访问控制能力(主要是写操作的严格顺序性)的分布式协调服务,其具有如下的设计目标。 ① 简单的数据模型,Zookeeper使得分布式程序能够通过一个共享的树形结构的名字空间来进行相互协调,即Zookeeper服务器内存中的数据模型由一系列被称为ZNode的数据节点组成,Zookeeper将全量的数据存储在内存中,以此来提高服务器吞吐、减少延迟的目的。 ② 可构建集群,一个Zookeeper集群通常由一组机器构成,组成Zookeeper集群的而每台机器都会在内存中维护当前服务器状态,并且每台机器之间都相互通信。 ③ 顺序访问,对于来自客户端的每个更新请求,Zookeeper都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序。 ④ 高性能,Zookeeper将全量数据存储在内存中,并直接服务于客户端的所有非事务请求,因此它尤其适用于以读操作为主的应用场景。 2.2 基本概念 ① 集群角色,最典型的集群就是Master/Slave模式(主备模式),此情况下把所有能够处理写操作的机器称为Master机器,把所有通过异步复制方式获取最新数据,并提供读服务的机器为Slave机器。Zookeeper引入了Leader、Follower、Observer三种角色,Zookeeper集群中的所有机器通过Leaser选举过程来选定一台被称为Leader的机器,Leader服务器为客户端提供写服务,Follower和Observer提供读服务,但是Observer不参与Leader选举过程,不参与写操作的过半写成功策略,Observer可以在不影响写性能的情况下提升集群的性能。 ② 会话,指客户端会话,一个客户端连接是指客户端和服务端之间的一个TCP长连接,Zookeeper对外的服务端口默认为2181,客户端启动的时候,首先会与服务器建立一个TCP连接,从第一次连接建立开始,客户端会话的生命周期也开始了,通过这个连接,客户端能够心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接受来自服务器的Watch事件通知。 ③ 数据节点,第一类指构成集群的机器,称为机器节点,第二类是指数据模型中的数据单元,称为数据节点-Znode,Zookeeper将所有数据存储在内存中,数据模型是一棵树,由斜杠/进行分割的路径,就是一个ZNode,如/foo/path1,每个ZNode都会保存自己的数据内存,同时还会保存一些列属性信息。ZNode分为持久节点和临时节点两类,持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上,而临时节点的生命周期和客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时节点都会被移除。另外,Zookeeper还允许用户为每个节点添加一个特殊的属性:SEQUENTIAL。一旦节点被标记上这个属性,那么在这个节点被创建的时候,Zookeeper会自动在其节点后面追加一个整形数字,其是由父节点维护的自增数字。 ④ 版本,对于每个ZNode,Zookeeper都会为其维护一个叫作Stat的数据结构,Stat记录了这个ZNode的三个数据版本,分别是version(当前ZNode的版本)、cversion(当前ZNode子节点的版本)、aversion(当前ZNode的ACL版本)。 ⑤ Watcher,Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,Zookeeper服务端会将事件通知到感兴趣的客户端。 ⑥ ACL,Zookeeper采用ACL(Access Control Lists)策略来进行权限控制,其定义了如下五种权限: · CREATE:创建子节点的权限。 · READ:获取节点数据和子节点列表的权限。 · WRITE:更新节点数据的权限。 · DELETE:删除子节点的权限。 · ADMIN:设置节点ACL的权限。  2.3 ZAB协议 Zookeeper使用了Zookeeper Atomic…

【分布式】Chubby与Paxos

一、前言 在上一篇理解了Paxos算法的理论基础后,接下来看看Paxos算法在工程中的应用。 二、Chubby Chubby是一个面向松耦合分布式系统的锁服务,GFS(Google File System)和Big Table等大型系统都是用它来解决分布式协作、元数据存储和Master选举等一些列与分布式锁服务相关的问题。Chubby的底层一致性实现就是以Paxos算法为基础,Chubby提供了粗粒度的分布式锁服务,开发人员直接调用Chubby的锁服务接口即可实现分布式系统中多个进程之间粗粒度的同控制,从而保证分布式数据的一致性。 2.1 设计目标 Chubby被设计成为一个需要访问中心化的分布式锁服务。 ① 对上层应用程序的侵入性更小,使用一个分布式锁服务的接口方式对上层应用程序的侵入性更小,应用程序只需调用相应的接口即可使用分布式一致性特性,并且更易于保持系统已有的程序结构和网络通信模式。 ② 便于提供数据的发布与订阅,在Chubby进行Master选举时,需要使用一种广播结果的机制来向所有客户端公布当前Master服务器,这意味着Chubby应该允许其客户端在服务器上进行少量数据的存储和读取(存储主Master地址等信息),也就是对小文件的读写操作。数据的发布与订阅功能和锁服务在分布式一致性特性上是相通的。 ③ 开发人员对基于锁的接口更为熟悉,Chubby提供了一套近乎和单机锁机制一直的分布式锁服务接口。 ④ 更便捷地构建更可靠的服务,Chubby中通常使用5台服务器来组成一个集群单元(Cell),根据Quorum机制(在一个由若干个机器组成的集群中,在一个数据项值的选定过程中,要求集群中过半的机器达成一致),只要整个集群中有3台服务器是正常运行的,那么整个集群就可以对外提供正常的服务。 ⑤ 提供一个完整的、独立的分布式锁服务,Chubby对于上层应用程序的侵入性特别低,对于Master选举同时将Master信息等级并广播的场景,应用程序只需要向Chubby请求一个锁,并且在获得锁之后向相应的锁文件写入Master信息即可,其余的客户端就可以通过读取这个锁文件来获取Master信息。 ⑥ 提供粗粒度的锁服务,Chubby针对的应用场景是客户端获得锁之后会进行长时间持有(数小时或数天),而非用于短暂获取锁的场景。当锁服务短暂失效时(服务器宕机),Chubby需要保持所有锁的持有状态,以避免持有锁的客户端出现问题。而细粒度锁通常设计为为锁服务一旦失效就释放所有锁,因为其持有时间很短,所以其放弃锁带来的代价较小。 ⑦ 高可用、高可靠,对于一个由5太机器组成的集群而言,只要保证3台正常运行的机器,整个集群对外服务就能保持可用,另外,由于Chubby支持通过小文件读写服务的方式来进行Master选举结果的发布与订阅,因此在Chubby的实际应用中,必须能够支撑成百上千个Chubby客户端对同一个文件进行监控和读取。 ⑧ 提供时间通知机制,Chubby客户端需要实时地感知到Master的变化情况,这可以通过让你客户端反复轮询来实现,但是在客户端规模不断增大的情况下,客户端主动轮询的实时性效果并不理想,且对服务器性能和网络带宽压力都非常大,因此,Chubby需要有能力将服务端的数据变化情况以时间的形式通知到所有订阅的客户端。 2.2 技术架构 Chubby的整个系统结构主要由服务端和客户端两部分组成,客户端通过RPC调用和服务端进行通信,如下图所示。 一个典型的Chubby集群(Chubby Cell),通常由5台服务器组成,这些副本服务器采用Paxos协议,通过投票的方式来选举产生一个获得过半投票的服务器作为Master,一旦成为Master,Chubby就会保证在一段时间内不会再有其他服务器成为Master,这段时期称为Master租期(Master Lease),在运行过程中,Master服务器会通过不断续租的方式来延长Master租期,而如果Master服务器出现故障,那么余下的服务器会进行新一轮的Master选举,最终产生新的Master服务器,开始新的Master租期。 集群中的每个服务器都维护着一份服务端数据库的副本,但在实际运行过程中,只有Master服务器才能对数据库进行写操作,而其他服务器都是使用Paxos协议从Master服务器上同步数据库数据的更新。 Chubby客户端通过向记录有Chubby服务端机器列表的DNS来请求获取所有的Chubby服务器列表,然后逐一发起请求询问该服务器是否是Master,在这个询问过程中,那些非Master的服务器,则会将当前Master所在的服务器标志反馈给客户端,这样客户端就能很快速的定位到Master服务器了。 只要该Master服务器正常运行,那么客户端就会将所有的请求都发送到该Master服务器上,针对写请求,Master会采用一致性协议将其广播给集群中所有的副本服务器,并且在过半的服务器接受了该写请求后,再响应给客户端正确的应答,而对于读请求,则不需要在集群内部进行广播处理,直接由Master服务器单独处理即可。 若该Master服务器发生故障,那么集群中的其他服务器会在Master租期到期后,重新开启新的一轮Master选举,通常一次Master选举大概花费几秒钟的时间,而如果其他副本服务器崩溃,那么整个集群继续工作,该崩溃的服务器会在恢复之后自动加入到Chubby集群中去,新加入的服务器首先需要同步Chubby最新的数据库数据,完成数据库同步之后,新的服务器就可以加入到正常的Paxos运作流程中与其他服务器副本一起协同工作。若崩溃后几小时后仍无法恢复工作,那么需要加入新的机器,同时更新DNS列表(新IP代替旧IP),Master服务器会周期性地轮询DNS列表,因此会很快感知服务器地址的变更,然后Master就会将集群数据库中的地址列表做相应的变更,集群内部的其他副本服务器通过复制方式就可以获取到最新的服务器地址列表了。 2.3 目录与文件 Chubby对外提供了一套与Unix文件系统非常相近但是更简单的访问接口。Chubby的数据结构可以看作是一个由文件和目录组成的树,其中每一个节点都可以表示为一个使用斜杠分割的字符串,典型的节点路径表示如下: /ls/foo/wombat/pouch…

【分布式】一致性协议

一、前言 继续前面的学习,这篇我们来学习在分布式系统中最重要的一块,一致性协议,其中就包括了大名鼎鼎的Paxos算法。 二、2PC与3PC 在分布式系统中,每一个机器节点虽然能够明确知道自己在进行事务操作过程中的结果是成功或是失败,但是却无法直接获取到其他分布式节点的操作结果,因此,当一个事务操作需要跨越多个分布式节点的时候,为了保持事务处理的ACID的特性,需要引入协调者的组件来统一调度所有分布式节点的执行逻辑,而被调度的节点则被称为参与者,协调者负责调度参与者的行为并最终决定这些参与者是否要把事务真正进行提交,基于这个思想,衍生出了二阶段提交和三阶段提交两种协议。 2.1 2PC 2PC为Two-Phase Commit的简写,为二阶段提交协议将事务的提交过程分成了两个阶段来进行处理,并执行如下流程: 阶段一:提交事务请求 ① 事务询问,协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。 ② 执行事务,各参与者节点执行事务操作(已经执行),并将Undo和Redo信息记入事务日志中。 ③ 各参与者向协调者反馈事务询问的响应,如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行;如果参与者没有成功执行事务,那么就反馈给协调者No响应,表示事务不可以执行。 第一阶段近似于是协调者组织各参与者对一次事务操作的投票表态的过程,因此二阶段提交协议的阶段一也被称为投票阶段。 阶段二:执行事务提交 协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作,正常情况包含如下两种可能: 1. 执行事务提交,假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务提交。 ① 发送提交请求,协调者向所有参与者节点发出Commit请求。 ② 事务提交,参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。 ③ 反馈事务提交结果,参与者在完成事务提交之后,向协调者发送Ack消息。 ④ 完成事务,协调者接收到所有参与者反馈的Ack消息后,完成事务。 2. 中断事务,假如任意一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到参与者的反馈响应,就会中断事务。 ① 发送回滚请求,协调者向所有参与者节点发出Rollback请求。 ② 事务回滚,参与者接收到Rollback请求后,会利用其在阶段一中记录的Undo信息来执行事务回滚,并在完成回滚之后释放在整个事务执行期间占用的资源。 ③ 反馈事务回滚结果,参与者在完成事务回滚后,向协调者发送Ack消息。 ④ 中断事务,协调者接收所有参与者反馈的Ack消息后,完成事务中断。 二阶段提交协议的优点:原理简单,实现方便。缺点:同步阻塞,单点问题,数据不一致,太过保守。 同步阻塞:在二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态,即当参与者占有公共资源时,其他节点访问公共资源不得不处于阻塞状态。 单点问题:若协调器出现问题,那么整个二阶段提交流程将无法运转,若协调者是在阶段二中出现问题时,那么其他参与者将会一直处于锁定事务资源的状态中,而无法继续完成事务操作。 数据不一致:在二阶段的阶段二,执行事务提交的时候,当协调者向所有的参与者发送Commit请求之后,发生了局部网络异常或者是协调者在尚未发送完Commit请求之前自身发生了崩溃,导致最终只有部分参与者收到了Commit请求,于是会出现数据不一致的现象。…

【分布式】分布式架构

一、前言   在大数据系统中,分布式系统已经成为一个无法避免的组件,如zookeeper已经成为了工业届的标准。所以对于大数据的研究,也必须要研究分布式系统的特点。 二、集中式系统 由一台或多台计算机组成的中心节点,数据集中存储在这个中心节点中,并且整个系统的所有业务单元都集中部署在这个中心节点上,系统的所有功能均由其集中处理。其部署简单,不用考虑多个节点间的分布式协作问题。 三、分布式系统 分布式系统是一个由硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。其拥有如下特点 3.1 分布性 分布式系统中的多台计算机都会在空间中随意分布,同时,机器的分布情况也会随时变动。 3.2 对等性 分布式系统中的计算机没有主/从之分,既没有控制整个系统的主机,也没有被控制的从机,组成分布式系统的所有计算机节点都是对等的,副本指的是分布式系统对数据和服务提供的一种冗余方式,为了对外提供高可用的服务,我们往往会对数据和服务进行副本处理。数据副本是指在不同的节点上持久化同一份数据,当某一个节点上存储的数据丢失时,可以从副本上读取到该数据,这是解决分布式系统数据丢失问题最为有效的手段。服务副本是只多个节点提供同样的服务,每个节点都有能力接受来自外部的请求并进行相应的处理。 3.3 并发性 同一分布式系统中的多个节点,可能会并发地操作一些共享资源,诸如数据库或分布式存储等,如何高效地协调分布式并发操作也成为了分布式系统架构与设计中最大的挑战之一。 3.4 缺乏全局时钟 典型的分布式系统由一系列在空间上随意分布的多个进程组成,具有明显的分布性,这些进程之间通过交换消息来进行互相通信,因此,在分布式系统中,很难定义两个时间究竟谁先谁后,原因就是因为分布式系统缺乏一个全局的时钟序列控制。 3.5 故障总是会发生 组成分布式系统的所有计算机,都有可能发生任何形式的故障,任何在设计阶段考虑到的异常情况,一定会在系统实际运行中发生。 四、分布式环境的问题 4.1 通信异常 从集中式到分布式,必然引入了网络因素,而由于网络本身的不可靠性,因此就引入了额外的问题。分布式系统各节点之间的网络通信能够正常进行,其延时也会远大于单机操作,在消息的收发过程中,消息丢失和消息延迟变得十分普遍。 4.2 网络分区 当网络发生异常情况时,导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式胸的所有节点中,只有部分节点之间能够正常通信,而另一些节点则不能,这种现象称之为网络分区,当网络分区出现时,分布式系统会出现局部小集群,在极端情况下,这些局部小集群会独立完成原本需要整个分布式系统才能完成的功能,包括对数据的事务处理,这就对分布式一致性提出了非常大的挑战。 4.3 三态 由于网络可能会出现各种各样的问题,因此分布式系统的每一次请求与响应,存在特有的三态概念:成功、失败、超时。当网络在异常情况下,可能会出现超时现象,通常由以下两种情况:1. 由于网络原因,该请求并没有被成功地发送到接收方,而是在发送过程就发生了消息丢失现象。2. 该请求成功的被接收方接受后,并进行了处理,但是在将响应反馈给发送方时,发生了消息丢失现象。 4.4 节点故障 节点故障是指组成分布式系统的服务器节点出现宕机或僵死现象,每个节点都有可能出现故障,并且煤炭都在发生。 五、从ACID到CAP/BASE 5.1 ACID 事务是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行单元,狭义上的食物特指数据库事务。一方面,当多个应用程序并发访问数据库时,食物可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作相互干扰,另一方面,食物为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在宜昌状态下仍能保持数据一致性的方法。事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),简称ACID。…

【目录】Zookeeper目录

Zookeeper的目录整理如下 1. 【分布式】分布式架构 2. 【分布式】一致性协议 3. 【分布式】Chubby与Paxos 4. 【分布式】Zookeeper与Paxos 5. 【分布式】Zookeeper使用–命令行 6. 【分布式】Zookeeper使用–Java API 7. 【分布式】Zookeeper使用–开源客户端 8. 【分布式】Zookeeper应用场景 9. 【分布式】Zookeeper在大型分布式系统中的应用 10. 【分布式】Zookeeper系统模型 11. 【分布式】Zookeeper序列化及通信协议 12. 【分布式】Zookeeper客户端 13. 【分布式】Zookeeper会话 14. 【分布式】Zookeeper服务端启动 15. 【分布式】Zookeeper的Leader选举 16. 【分布式】Zookeeper的服务器角色 17. 【分布式】Zookeeper请求处理 18. 【分布式】Zookeeper数据与存储

【分布式】Zookeeper数据与存储

一、前言 前面分析了Zookeeper对请求的处理,本篇博文接着分析Zookeeper中如何对底层数据进行存储,数据存储被分为内存数据存储于磁盘数据存储。 二、数据与存储 2.1 内存数据 Zookeeper的数据模型是树结构,在内存数据库中,存储了整棵树的内容,包括所有的节点路径、节点数据、ACL信息,Zookeeper会定时将这个数据存储到磁盘上。 1. DataTree DataTree是内存数据存储的核心,是一个树结构,代表了内存中一份完整的数据。DataTree不包含任何与网络、客户端连接及请求处理相关的业务逻辑,是一个独立的组件。 2. DataNode DataNode是数据存储的最小单元,其内部除了保存了结点的数据内容、ACL列表、节点状态之外,还记录了父节点的引用和子节点列表两个属性,其也提供了对子节点列表进行操作的接口。 3. ZKDatabase Zookeeper的内存数据库,管理Zookeeper的所有会话、DataTree存储和事务日志。ZKDatabase会定时向磁盘dump快照数据,同时在Zookeeper启动时,会通过磁盘的事务日志和快照文件恢复成一个完整的内存数据库。 2.2 事务日志 1. 文件存储 在配置Zookeeper集群时需要配置dataDir目录,其用来存储事务日志文件。也可以为事务日志单独分配一个文件存储目录:dataLogDir。若配置dataLogDir为/home/admin/zkData/zk_log,那么Zookeeper在运行过程中会在该目录下建立一个名字为version-2的子目录,该目录确定了当前Zookeeper使用的事务日志格式版本号,当下次某个Zookeeper版本对事务日志格式进行变更时,此目录也会变更,即在version-2子目录下会生成一系列文件大小一致(64MB)的文件。 2. 日志格式 在配置好日志文件目录,启动Zookeeper后,完成如下操作 (1) 创建/test_log节点,初始值为v1。 (2) 更新/test_log节点的数据为v2。 (3) 创建/test_log/c节点,初始值为v1。 (4) 删除/test_log/c节点。 经过四步操作后,会在 将Zookeeper下的zookeeper-3.4.6.jar和slf4j-api-1.6.1.jar复制到。 java -classpath . org.apache.zookeeper.server.LogFormatter log.cec ZooKeeper Transactional…

【分布式】Zookeeper请求处理

一、前言 在前面学习了Zookeeper中服务器的三种角色及其之间的通信,接着学习对于客户端的一次请求,Zookeeper是如何进行处理的。 二、请求处理 2.1 会话创建请求 Zookeeper服务端对于会话创建的处理,大体可以分为请求接收、会话创建、预处理、事务处理、事务应用和会话响应六大环节,其大体流程如 1. 请求接收 (1) I/O层接收来自客户端的请求。NIOServerCnxn维护每一个客户端连接,客户端与服务器端的所有通信都是由NIOServerCnxn负责,其负责统一接收来自客户端的所有请求,并将请求内容从底层网络I/O中完整地读取出来。 (2) 判断是否是客户端会话创建请求。每个会话对应一个NIOServerCnxn实体,对于每个请求,Zookeeper都会检查当前NIOServerCnxn实体是否已经被初始化,如果尚未被初始化,那么就可以确定该客户端一定是会话创建请求。 (3) 反序列化ConnectRequest请求。一旦确定客户端请求是否是会话创建请求,那么服务端就可以对其进行反序列化,并生成一个ConnectRequest载体。 (4) 判断是否是ReadOnly客户端。如果当前Zookeeper服务器是以ReadOnly模式启动,那么所有来自非ReadOnly型客户端的请求将无法被处理。因此,服务端需要先检查是否是ReadOnly客户端,并以此来决定是否接受该会话创建请求。 (5) 检查客户端ZXID。正常情况下,在一个Zookeeper集群中,服务端的ZXID必定大于客户端的ZXID,因此若发现客户端的ZXID大于服务端ZXID,那么服务端不接受该客户端的会话创建请求。 (6) 协商sessionTimeout。在客户端向服务器发送超时时间后,服务器会根据自己的超时时间限制最终确定该会话超时时间,这个过程就是sessionTimeout协商过程。 (7) 判断是否需要重新激活创建会话。服务端根据客户端请求中是否包含sessionID来判断该客户端是否需要重新创建会话,若客户单请求中包含sessionID,那么就认为该客户端正在进行会话重连,这种情况下,服务端只需要重新打开这个会话,否则需要重新创建。  2. 会话创建 (1) 为客户端生成sessionID。在为客户端创建会话之前,服务端首先会为每个客户端分配一个sessionID,服务端为客户端分配的sessionID是全局唯一的。 (2) 注册会话。向SessionTracker中注册会话,SessionTracker中维护了sessionsWithTimeout和sessionsById,在会话创建初期,会将客户端会话的相关信息保存到这两个数据结构中。 (3) 激活会话。激活会话涉及Zookeeper会话管理的分桶策略,其核心是为会话安排一个区块,以便会话清理程序能够快速高效地进行会话清理。 (4) 生成会话密码。服务端在创建一个客户端会话时,会同时为客户端生成一个会话密码,连同sessionID一同发给客户端,作为会话在集群中不同机器间转移的凭证。 3. 预处理 (1) 将请求交给PrepRequestProcessor处理器处理。在提交给第一个请求处理器之前,Zookeeper会根据该请求所属的会话,进行一次激活会话操作,以确保当前会话处于激活状态,完成会话激活后,则提交请求至处理器。 (2) 创建请求事务头。对于事务请求,Zookeeper会为其创建请求事务头,服务端后续的请求处理器都是基于该请求头来识别当前请求是否是事务请求,请求事务头包含了一个事务请求最基本的一些信息,包括sessionID、ZXID(事务请求对应的事务ZXID)、CXID(客户端的操作序列)和请求类型(如create、delete、setData、createSession等)等。 (3) 创建请求事务体。由于此时是会话创建请求,其事务体是CreateSessionTxn。…

【分布式】Zookeeper使用–命令行

一、前言 在学习了Zookeeper相关的理论知识后,下面接着学习对Zookeeper的相关操作。 二、Zookeeper部署 Zookeeper的部署相对来说还是比较简单,读者可以在网上找到相应的教程,点这里,笔者不再累赘。 Zookeeper有三种运行形式:集群模式、单机模式、伪集群模式。 以下实验都是在单机模式下进行。 三、服务端   bin目录下常用的脚本解释 zkCleanup  清理Zookeeper历史数据,包括食物日志文件和快照数据文件 zkCli      Zookeeper的一个简易客户端 zkEnv    设置Zookeeper的环境变量 zkServer     Zookeeper服务器的启动、停止、和重启脚本 3.1 运行服务 进入bin目录,使用zkServer.sh start启动服务 使用jps命令查看,存在QuorumPeerMain进程,表示Zookeeper已经启动 3.2 停止服务 在bin目录下,使用zkServer.sh stop停止服务 使用jps命令查看,QuorumPeerMain进程已不存在,表示Zookeeper已经关闭 四、客户端 4.1 打开客户端 在服务端开启的情况下,运行客户端,使用如下命令:. 连接服务端成功,若连接不同的主机,可使用如下命令:. -server ip:port 可以使用帮助命令help来查看客户端的操作 4.2 创建节点 使用create命令,可以创建一个Zookeeper节点, 如 create [-s] [-e]…

【分布式】Zookeeper使用–Java API

一、前言 上一篇博客我们通过命令行来操作Zookeper的客户端和服务端并进行相应的操作,这篇主要介绍如何通过API(JAVA)来操作Zookeeper。 二、开发环境配置 首先打开Zookeeper服务端(上一篇博客有具体的方法),方便客户端连接。 配置开发环境环境可以有两种方式:① 直接下载相关的依赖Jar包,然后在IDE中添加依赖 ② 建立maven项目,使用maven进行依赖管理。 ① 手动添加依赖至IDE 步骤一:点击这里下载对应版本的Jar包,包括(jar、javadoc.jar、sources.jar),笔者对应下载的Zookeeper3.4.6版本。 步骤二:打开IDE(笔者使用eclispe),新建名为zookeeper_examples_none_maven的java项目。由于需要单独添加依赖,为了方便管理,笔者在项目下新建了jar文件夹,用于存放本项目的jar包(将步骤一下载的3个jar包存放至此文件夹下)。 步骤三:在eclipse中添加依赖 步骤四:新建包、Java类进行测试 Zookeeper_Constructor_Usage_Simple.java package com.hust.grid.leesf.examples; import java.io.IOException; import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooKeeper; public class Zookeeper_Constructor_Usage_Simple implements Watcher { private static CountDownLatch connectedSemaphore =…