`
wbj0110
  • 浏览: 1602081 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Zookeeper注册节点的掉线自动重新注册及测试方法

阅读更多

在一套分布式的online services系统中,各service通常不会放在一台服务器上,而是通过Zookeeper这样的东西,将自己的service信息注册到上面,service的使用者通过Zookeeper来发现各service的信息,从而可以将request发送到不同的service上去处理。

service register on Zookeeper

如上图所示,两个Service Provider 1和2分别在192.168.1.5和192.168.1.6这两台服务器的2688端口上提供服务,服务的地址和端口注册到了Zookeeper中。Service User通过查询Zookeeper,可得知这些服务的信息。通常,Service User与Service Provider之间的通信,是通过connection pool实现的,因为Service User不可能假定在第一次查询到所有Service Provider的信息之后,它们就是一直存活的,假如某个Service Provider因为程序问题死掉了,向它发送request只会造成大量的失败结果,因此通常会实现一个connection pool来保证实时更新节点的信息,当有一个Service Provider从Zookeeper上消失之后,从connection pool中取出的connection总是可用的(即:总能通过它把request发送到一个有效的Service Provider那里)。
文章来源:http://www.codelast.com/
这里,我们保证了当一个Service Provider从Zookeeper上退出后,我们一定不会再用它,但是,我们如何保证一个Service Provider还存活的情况下,都能处于可服务的状态呢?例如,Service Provider 1的程序工作一直很稳定,但是某天由于ISP的原因,它和Zookeeper之间的网络中断了5分钟,于是Zookeeper会无法向它发送心跳包,最终Zookeeper会认为session expired了,从而会把它注册的临时节点给移除掉(必须是注册临时节点啊,要不然当Service Provider挂了之后节点还在,岂不出乱子了)。移除掉之后,问题就来了:5分钟后中断的网络恢复正常了,Service Provider 1的程序也一直没有死掉,它又可以serving了,但是由于它在Zookeeper中注册的节点没了,所以Service User通过connection pool是永远也无法向Service Provider 1发送request的,于是所有的request还是都发到了Service Provider 2那里,造成它的负载一直很大,系统的处理能力减弱。
因此,为了避免这种问题,我们需要在Service Provider中提供Zookeeper掉线自动重新注册的功能。
【1】用Java怎么注册Zookeeper
Curator库是一个绝好的选择。它是Netflix开发的一套开源软件。
什么?没听说过Netflix?全美三分之一的带宽都是被这家公司占用的你不知道?
好吧,那么火爆得一塌糊涂的美剧《纸牌屋》你总听说过吧?就是这家公司花钱制作的。如果这也没听说过的话,那么你只能去Google啦。
题外话:科技和生活娱乐息息相关啊!
如果要问为什么不直接用Zookeeper官方的API,而是使用包装过的Curator,那只能用一句话来解释:Curator很好很强大很方便。
文章来源:http://www.codelast.com/
【2】代码
『A』使用Curator注册Zookeeper的代码

1
2
3
4
5
6
7
8
CuratorFramework curator = CuratorFrameworkFactory.newClient("zookeeper.codelast.com:2181",
  5000, 3000, new RetryNTimes(5, 1000));
curator.start();
String regContent = "192.168.1.5:2688";
String zkRegPathPrefix = "/codelast/service-provider-";
//TODO:
curator.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
      .forPath(zkRegPathPrefix, regContent.getBytes("UTF-8"));

解释一下:
zookeeper.codelast.com:2181 是你的Zookeeper server的host:port。
192.168.1.5:2688 是注册的Zookeeper节点的内容,表示Service Provider 1在1912.168.1.5的2688端口提供服务。当你用Zookeeper客户端zkCli.sh的get命令时,获取的返回值的第一行就是这个内容。
CreateMode.EPHEMERAL_SEQUENTIAL 表示注册的节点是临时的,并且其命名是顺序增加的。
/codelast/service-provider- 是把service注册到Zookeeper中的哪个路径下。上面代码的效果就是,注册的节点的完整路径会类似于 /codelast/service-provider-0000000001
文章来源:http://www.codelast.com/
『B』上面的代码在session expired的情况下,是无法自动重新在Zookeeper中注册的。要实现这种功能,需要添加一个实现了ConnectionStateListener接口的类,并应用到CuratorFramework对象上。我们需要在上面代码中的“TODO”处添加如下代码:

1
2
MyConnectionStateListener stateListener = new MyConnectionStateListener(zkRegPathPrefix, regContent);
curator.getConnectionStateListenable().addListener(stateListener);

然后再实现MyConnectionStateListener类:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * A class to monitor connection state & re-register to Zookeeper when connection lost.
 *
 * @author Darran Zhang @ codelast.com
 */
public class MyConnectionStateListener implements ConnectionStateListener {
  private String zkRegPathPrefix;
  private String regContent;
  
  public MyConnectionStateListener(String zkRegPathPrefix, String regContent) {
    this.zkRegPathPrefix = zkRegPathPrefix;
    this.regContent = regContent;
  }
  
  @Override
  public void stateChanged(CuratorFramework curatorFramework, ConnectionState connectionState) {
    if (connectionState == ConnectionState.LOST) {
      while (true) {
        try {
          if (curatorFramework.getZookeeperClient().blockUntilConnectedOrTimedOut()) {
            curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
      .forPath(zkRegPathPrefix, regContent.getBytes("UTF-8"));
            break;
          }
        } catch (InterruptedException e) {
          //TODO: log something
          break;
        } catch (Exception e) {
          //TODO: log something
        }
      }
    }
  }
}

文章来源:http://www.codelast.com/
此类负责监听connection的状态,并在检测到LOST状态时(此时client已经从Zookeeper中掉线)重新注册。
注意,在检测到LOST状态后,上面的代码用了一个while (true) 死循环来不断尝试重新连接Zookeeper server,连不上不罢休。

【3】测试
如何测试?当然要创造出一种session expired的情况,让Zookeeper server把它认为已经掉线的节点的注册信息给移除掉。怎么让session expire呢?官方网站上有这么一段话

Is there an easy way to expire a session for testing?
 
Yes, a ZooKeeper handle can take a session id and password. This constructor is used to recover a session after total application failure. For example, an application can connect to ZooKeeper, save the session id and password to a file, terminate, restart, read the session id and password, and reconnect to ZooKeeper without loosing the session and the corresponding ephemeral nodes. It is up to the programmer to ensure that the session id and password isn't passed around to multiple instances of an application, otherwise problems can result.
 
In the case of testing we want to cause a problem, so to explicitly expire a session an application connects to ZooKeeper, saves the session id and password, creates another ZooKeeper handle with that id and password, and then closes the new handle. Since both handles reference the same session, the close on second handle will invalidate the session causing a SESSION_EXPIRED on the first handle.

文章来源:http://www.codelast.com/
但是需要这么麻烦吗?直接通过OS的防火墙就可以做到。例如,在RedHat上,通过如下命令:

1
iptables -A INPUT -d codelast.com -p tcp --sport 2181 -j DROP

你将可以阻止来自codelast.com这个域名的所有输入(INPUT)的流量。这会导致Zookeeper server和client之间的心跳失效,互相认为对方已经掉线了。对Zookeeper server来说,当它认为client掉线时,就会把client节点从Zookeeper中移除。这个时候,如果client程序没有重新注册的能力,那么当网络恢复后,client程序虽然是能正常运行的,但是也失去了提供service的能力——因为service的使用者已经无法通过Zookeeper发现它了。
我们先启动Service Provider,然后利用执行上面的命令(如果不是RedHat,请自行Google)阻断网络连接一段时间,你最终将会观察到Zookeeper中注册的节点已经没了,也就是说我们让session expired了。
然后,执行如下命令:

1
iptables -F

文章来源:http://www.codelast.com/
该命令可以恢复防火墙的设置。此时,网络恢复连接,你会看到Curator打印出来很多信息,提示已经重新连接上了Zookeeper server。但是注意,如果你没有像前面的代码一样提供自动重新注册的能力,那么,先前在Zookeeper中注册的节点并不会出现!也就是说,连上了也没用,它已经不能被发现了。
在添加了自动重新注册的功能后,Zookeeper中注册的节点就会自动重新被创建出来了。这就达到了我们要的效果。

http://www.codelast.com/?p=6049

 
分享到:
评论

相关推荐

    zookeeper之节点基本操作(一).doc

    ### ZooKeeper节点基本操作详解 #### 一、创建节点 在ZooKeeper中,节点(也称为znode)是用于存储数据的基本单元。通过`create`命令可以创建节点,并且可以指定不同的节点类型。 1. **普通节点**: - 普通节点...

    ZooInspector 用于查看zookeeper的节点信息

    临时节点在创建它的会话结束后自动删除,而持久节点直到被显式删除才会消失。 - 每个 znode 都有版本号,记录了该节点数据的修改次数。 2. **ZooInspector 功能**: - **节点浏览**:ZooInspector 允许用户逐级...

    Zookeeper单节点注册中心

    单节点的Zookeeper部署相对简单,适用于学习和测试环境。以下是一个详细的步骤: 1. **安装Java运行环境**:Zookeeper基于Java编写,所以首先需要在服务器上安装Java运行环境,确保JDK版本在1.6以上。 2. **下载...

    MAC上查看Zookeeper节点工具

    在MAC操作系统上,我们有时需要对Zookeeper的节点数据进行查看和管理,这时就需要用到特定的工具。本文将详细介绍如何在MAC上使用名为"ZooInspector"的工具来查看Zookeeper节点。 ZooInspector是一个图形化的...

    JAVA实现zookeeper节点批量删除工具类.rar

    在Java编程环境中,ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。本资源提供了一个JAVA实现的Zookeeper节点...

    基于zookeeper临时顺序节点实现分布式调度

    2. **顺序性**:当创建临时或持久节点时,Zookeeper会在节点名后自动添加一个序列号,表示创建顺序。这种特性可以用来解决分布式环境中的竞争问题,比如分布式锁。 **分布式锁的实现**: 1. **锁的创建**:每个...

    Zookeeper数据节点可视化查看工具

    Zookeeper数据节点可视化查看工具; 下载解压后即可使用; 内有说明文本。 Zookeeper数据节点可视化查看工具; 下载解压后即可使用; 内有说明文本。 Zookeeper数据节点可视化查看工具; 下载解压后即可使用...

    shell脚本监控zookeeper集群节点异常发送邮件通知.rar

    总之,这个“shell脚本监控zookeeper集群节点异常发送邮件通知”方案提供了一种自动化监控和故障通知的方法,对于保障Zookeeper集群的稳定性和提高运维效率具有重要意义。通过学习和应用这个脚本,我们可以更好地...

    zookeeper之节点基本操作.zip

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终将简单易用的接口和性能高效、功能稳定的系统提供给用户。...

    zookeeper之节点基本操作一 zookeeper节点有哪些

    zookeeper之节点基本操作(一)

    zookeeper节点类型和java客户端创建zk节点

    在创建节点时,Zookeeper会在节点名称后自动追加一个递增的数字,例如“/mydata-000000001”。 - 这种机制常用于生成全局唯一ID,或者在分布式环境中实现排序。 4. **临时顺序节点(Ephemeral Sequential Nodes)*...

    java-architect-zookeeper之节点基本操作(一)

    java zookeeper之节点基本操作(一) zookeeper之节点基本操作(一) zookeeper之节点基本操作(一) zookeeper之节点基本操作(一) zookeeper之节点基本操作(一)

    zookeeper之节点基本操作(一),节点znodes

    一旦客户端与 ZooKeeper 服务器之间的会话结束,所有由该客户端创建的临时节点将自动被删除。这种特性使得临时节点非常适合用来实现临时状态或者表示某些暂时性的任务,如选举领导者时的候选者标识等。 ##### 3. ...

    Zookeeper以及kafka单节点发、服务部署

    ### Zookeeper及Kafka单节点部署详解 #### 一、Zookeeper单节点部署步骤与原理 **1. 安装介质准备** 为了部署Zookeeper单节点环境,首先需要下载安装包,官方提供的下载链接为:...

    zookeeper实现服务节点HA主备自动切换,1主多从模式、ZooKeeper实现高可用

    然后,我们可以通过定义服务实例,将其注册到ZooKeeper,当服务节点状态改变时,ZooKeeper会自动更新这些信息,让其他服务能够实时感知到。 此外,Spring Framework的事件驱动模型也能与ZooKeeper的监听机制相结合...

    zookeeper之节点基本操作.docx

    本文详细介绍了 ZooKeeper 中的基本节点操作方法,包括节点的创建、读取、更新和删除。通过这些基本操作,开发者能够在分布式系统中有效地管理和协调数据。对于初学者来说,理解这些基础操作是学习 ZooKeeper 的第一...

    zookeeper两节点提交流程原理

    zookeeper两节点提交流程原理

    基于Apache ZooKeeper和ActiveMQ的分布式软件测试方法.pdf

    总的来说,本文档详细介绍了基于Apache ZooKeeper和ActiveMQ的分布式软件测试方法,重点解析了ZooKeeper在配置管理和集群管理中的应用,以及如何在Java平台中实现自动化节点注册。文章不仅分享了理论知识,还提供了...

Global site tag (gtag.js) - Google Analytics