http://blog.csdn.net/chenyi8888/article/details/6626302
Zookeeper的Client直接与用户打交道,是我们使用Zookeeper的interface。了解ZK Client的结构和工作原理有利于我们合理的使用ZK,并能在使用中更早的发现问题。本文将在研究源码的技术上讲述ZK Client的工作原理及内部工作机制。
在看完ZK Client的大致架构以后我希望能有一种简单的方式描述ZK Client的基本结构,想来想去我觉得还是图片比较能反映情况,于是我画了这张大致的结构图:
我想既然我画了这张图,就让我们从这张图开始讲起吧。
模块:
我们可以认为ZK的Client由三个主要模块组成:Zookeeper, WatcherManager, ClientCnxn
Zookeeper是ZK Client端的真正接口,用户可以操作的最主要的类,当用户创建一个Zookeeper实例以后,几乎所有的操作都被这个实例包办了,用户不用关心怎么连接到Server,Watcher什么时候被触发等等令人伤神的问题。
WatcherManager,顾名思义,它是用来管理Watcher的,Watcher是ZK的一大特色功能,允许多个Client对一个或多个ZNode进行监控,当ZNode有变化时能够通知到监控这个ZNode的各个Client。我们把一个ZK Client简单看成一个Zookeeper实例,那么这个实例内部的WatcherManager就管理了ZK Client绑定的所有Watcher。
ClientCnxn是管理所有网络IO的模块,所有和ZK Server交互的信息和数据都经过这个模块,包括给ZK Server发送Request,从ZK Server接受Response,以及从ZK Server接受Watcher Event。ClientCnxn完全管理了网络,从外部看来网络操作是透明的。
线程:
每当我们创建一个Zookeeper实例的时候,会有两个线程被创建:SendThread和EventThread。所以当我们使用ZK Client端的时候应该尽量只创建一个Zookeeper实例并反复使用。大量的创建销毁Zookeeper实例不仅会反复的创建和销毁线程,而且会在Server端创建大量的Session。
SendThread是真正处理网络IO的线程,所有通过网络发送和接受的数据包都在这个线程中处理。这个线程的主体是一个while循环:
while (zooKeeper.state.isAlive()) {
try {
if (sockKey == null) {
// don’t re-establish connection if we are closing
if (closing) {
break;
}
startConnect();
lastSend = now;
lastHeard = now;
}
… ….
selector.select(to);
Set<SelectionKey> selected;
synchronized (this) {
selected = selector.selectedKeys();
}
// Everything below and until we get back to the select is
// non blocking, so time is effectively a constant. That is
// Why we just have to do this once, here
now = System.currentTimeMillis();
for (SelectionKey k : selected) {
… …
if (doIO()) {
lastHeard = now;
}
… …
}
}
catch() {
… …
}
}
这里用了java的nio功能,当selector侦测到事件发生的时候就会触发一次循环,主要的操作会在doIO()里面完成:
boolean doIO() throws InterruptedException, IOException {
boolean packetReceived = false;
SocketChannel sock = (SocketChannel) sockKey.channel();
if (sock == null) {
throw new IOException(“Socket is null!”);
}
if (sockKey.isReadable()) {
… …
}
if (sockKey.isWritable()) {
… …
}
if (outgoingQueue.isEmpty()) {
disableWrite();
} else {
enableWrite();
}
return packetReceived;
}
这个过程大概是这样的:
1. 如果有数据可读,则读取数据包,如果数据包是先前发出去的Request的Response,那么这个数据包一定在Pending Queue里面。将它从Pending Queue里面移走,并将此信息添加到Waiting Event Queue 里面,如果数据包是一个Watcher Event,将此信息添加到Waiting Event Queue里面。
2. 如果OutgoingQueue里面有数据需要发送,则发送数据包并把数据包从Outgoing Queue移至Pending Queue,意思是数据我已经发出去了,但还要等待Server端的回复,所以这个请求现在是Pending 的状态。
另外一个线程EventThread是用来处理Event的。前面提到SendThread从Server收到数据的时候会把一些信息添加到Event Thread里面,比如Finish Event和Watcher Event。EventThread就是专门用来处理这些Event的,收到Finish Event的时候会把相对应的Package置成Finish状态,这样等待结果的Client函数就能得以返回。收到Watcher Event的时候会联系WatcherManager找到相对应的Watcher,从WatcherManager里面移除这个Watcher(因为每个Watcher只会被通知一次) 并回调Watcher的process函数。所以所有Watcher的process函数是运行在EventThread里面的。
保持连接:
到目前为止应该已经大概介绍了ZK Client端的大致结构和处理流程。还剩下一个问题就是当网络出问题时ZK Client是如何处理的。其实这个过程并不复杂,大概是执行以下步骤:
1. 网络发生故障,网络操作抛出的异常被捕获。
2. 确认网络操作失败,清除当前与Server相关的网络资源,包括Socket等等。
3. 在Server列表中逐个尝试链接Server。
这个过程从外界看来是透明的,外界并不会觉察到ZK Client已经悄悄地更换了一个连接的Server。
好了,对于ZK Client的介绍大概就这么多了,希望这样的介绍对于大家学习和使用Zookeeper有一些帮助。对于文章中没有介绍或者没有说清楚的地方需要进一步查看源码来解决。
分享到:
相关推荐
文章主要关注的是HBase数据读取流程中的Client-Server交互逻辑,这是理解HBase工作原理的关键部分。首先,客户端通过配置文件中的Zookeeper地址建立连接,Zookeeper在这里扮演着服务发现的角色。客户端会获取到`/...
《PyPI官网下载 | cls-client-1.3.0.tar.gz——Python库解析与应用》 在Python的世界中,PyPI(Python Package Index)是最重要的软件仓库,它为开发者提供了无数的第三方模块和库,方便他们构建自己的项目。本文将...
**Java 6.0 源码分析:Zookeeper-MQ——基于ZooKeeper的高可用消息队列** Zookeeper-MQ是一个基于Apache ZooKeeper构建的消息队列系统,它利用了ZooKeeper的分布式协调能力,实现了可靠的、高可用的消息传递功能。...
本次我们将深入探讨一个在PyPI官网下载的资源——"assisted-service-client-1.0.18.1.post30.tar.gz"。这个压缩包包含了名为"assisted-service-client"的Python库,版本号为1.0.18.1.post30,下面我们将详细解析它的...
本文将深入探讨从PyPI官网下载的资源——`instantlab_apiclient-0.2.4.tar.gz`,解析其核心功能、应用场景以及相关的技术栈,特别是与Zookeeper、分布式系统、云原生和Python库的关系。 `instantlab_apiclient-...
本文将深入探讨PyPI上下载的资源——onesaitplatform-client-services-1.0.0.tar.gz,这是一个与Zookeeper、分布式系统、云原生以及Python库相关的软件包,具有重要的学习和应用价值。 首先,让我们了解...
本文将深入探讨从PyPI官网下载的资源——`pspring-rest-client-0.0.19.tar.gz`,并围绕其相关的分布式、云原生以及Python库等核心概念进行详尽的解析。 首先,`pspring-rest-client`是一款基于Python的RESTful API...
这次我们关注的是在PyPI官网上可以找到的一个特定包——bmlx-openapi-client-0.0.90.8.tar.gz。这个压缩包包含了Python库bmlx-openapi-client的版本0.0.90.8,是开发者用来与某个开放API进行交互的重要工具。 首先...
《PyPI官网下载 | threedi_api_client-3.0b5.tar.gz——探索Python分布式云原生开发的利器》 PyPI(Python Package Index)是Python开发者们的重要资源库,其中包含了各种开源的Python库和模块。在此次讨论中,我们...
《PyPI官网下载:ndg_httpsclient-0.3.3.tar.gz——Python中的安全HTTPS客户端库解析》 在Python的开发过程中,安全地进行HTTP通信是至关重要的,特别是当涉及到敏感数据传输时。PyPI(Python Package Index)是...
《PyPI官网下载:pulpcore-client-3.8.0.dev1603111095.tar.gz——深入解析Python云原生库》 PyPI(Python Package Index)是Python开发者的重要资源库,它提供了众多开源的Python软件包,供全球的开发者们下载和...
描述进一步确认了这个资源的来源——PyPI官网,并提供了完整的资源名称,即`smart-rest-client-0.1.3.tar.gz`。 标签中包含"zookeeper"、"分布式"、"云原生"以及"cloud native"和"Python库",这些关键词揭示了该库...
今天我们将深入探讨一个特定的包——"backend.ai-client-1.1.9.tar.gz",这个包在PyPI官网上可得,它是backend.ai客户端的一个版本,具有与人工智能、zookeeper、分布式系统以及云原生技术紧密相关的特性。...
《深入解析Zookeeper源码:Java视角下的分布式协调机制》 在分布式系统中,Zookeeper以其高可用性、强一致性以及简洁的API成为了许多大型企业的首选协调服务。本篇文章将基于Java源码,深入剖析Zookeeper的核心机制...
4. 服务发现:在服务消费者端,通过监听Zookeeper上的服务注册路径,可以获取到所有在线服务提供者的列表。Spring Cloud的DiscoveryClient接口提供了便利的方法来获取这些信息。 5. 动态更新:当服务提供者数量发生...
《PyPI官网下载 | socialscan-1.2.3.tar.gz——Python库解析与应用》 在Python的世界里,PyPI(Python Package Index)是官方的软件仓库,它为开发者提供了一个集中发布和获取Python软件包的平台。本文将探讨的是在...
《PyPI官网下载 | localstripe-1.0.0.tar.gz——Python库解析与应用》 在Python的生态系统中,PyPI(Python Package Index)扮演着至关重要的角色,它是Python开发者获取、分享和安装第三方软件包的主要平台。本文...
《系统稳定性——Dubbo 常见错误及解决方法》 Dubbo,作为一个高性能的RPC框架,被全球众多企业广泛采用。在实际使用过程中,可能会遇到各种错误,本文将针对这些常见问题进行深入剖析,并提供相应的解决方案。 1....
<artifactId>hbase-client <version>1.4.6 ``` 接下来,我们将在Java程序中创建一个配置对象,通过它连接到HBase。这通常涉及设置ZooKeeper的地址,因为HBase的元数据存储在ZooKeeper中: ```java ...
《PyPI 官网下载 | visoptslider-1.0.0.tar.gz——探索Python库在分布式环境中的应用》 PyPI(Python Package Index)是Python开发者的重要资源库,它为全球的Python开发者提供了海量的第三方库,方便大家在开发...