设置ZooKeeper服务器地址列表源码解析及扩展

ZooKeeper zooKeeper = new ZooKeeper("192.168.109.130:2181",SESSION_TIMEOUT,new ZooKeeperFirstBlood());

在创建zk连接的时候,必须要获取到zk服务器集群的地址,最简单的方式是在构造函数中传入ip:port,ip2:port2,...,ipn:portn的形式,优势是简单,劣势也很明显,扩展性不强,一旦zk集群发生变动,整个就gg了。

本文主要先分析zk是如何去解析服务器地址,然后会给去使用动态获取zk服务器集群的方式。

zk最简单的解析

zk在构造函数对传入的connectString进行解析构造了 ConnectStringParser connectStringParser = new ConnectStringParser(connectString); 对象,ConnectStringParser是一个服务器地址列表解析器,主要作用是解析根目录和获取zk server地址

  1. 定义根目录

    相当于Linux的chroot命令,如果客户端设置了这个属性,那么所有的操作都会被限制在该命名空间下。具体使用方式:

    new Zookeeper("192.168.0.1:2181,192.168.0.2:2181/zktest/wpr")

  2. 解析zk地址

      String hostsList[] = connectString.split(",");
    for (String host : hostsList) {
    int port = DEFAULT_PORT;
    int pidx = host.lastIndexOf(':');
    if (pidx >= 0) {
    // otherwise : is at the end of the string, ignore
    if (pidx < host.length() - 1) {
    port = Integer.parseInt(host.substring(pidx + 1));
    }
    host = host.substring(0, pidx);
    }
    serverAddresses.add(InetSocketAddress.createUnresolved(host, port));
  3. 生成地址列表管理器HostProvider

    在ConnectStringParser解析器中将字符串封装为List对象,经过处理后地址列表会被进一步封装到StaticHostPorvider类中。

   /**
* The next host to try to connect to.
*
* For a spinDelay of 0 there should be no wait.
*
* 用于返回一个InetSocketAddress地址,这个方法的调用必须返回一个InetSocketAddress,不能为null和报错
* @param spinDelay
* Milliseconds to wait if all hosts have been tried once.
*/
public InetSocketAddress next(long spinDelay);
/**
* Notify the HostProvider of a successful connection.
*
* The HostProvider may use this notification to reset it's inner state.
*/
public void onConnected();

环形解析很多书已经解释过了,不是本文的重点

问题:

  1. zk服务器一旦迁移或者个别机器变更,会导致大批客户端应用变更。
  2. 部分情况下,为了增进系统的稳定性和容灾特性,需要配置一些特殊的规则,原来的环形解析肯定是不满足需求的

针对上面,主流的解决方案:地址列表管理器能够定时从DNS或者一个配置管理中心上解析出Zk服务器值列表,如果这个列表变更了,可以同时更新到serverAddress集合,这样在下次获取服务器地址的时候(调用next),可以获取到最新的服务器地址。

整体结构:

核心代码

本次主要是从配置中心去获取zk服务器的地址,在创建ZooKeeper对象的时候,仅仅使用一个HTTP地址,建立一个HTTP的长连接,去这个服务器上获取zk地址列表,定时去获取更新地址

public class DynamicHTTPHostProvider implements HostProvider {
/**
* zk服务器列表
*/
private final List<InetSocketAddress> domainAddresses = new ArrayList(5); public DynamicHTTPHostProvider(String domainURL) {
ADDRESS_SERVER_URL = domainURL;
start();
} public synchronized void start(){
//这个其实可以重新写到一个类里面
if(isStart){
log.warn("DynamicHTTPHostProvider already run");
return ;
}
GetServerListTask getServersTask = new GetServerListTask(ADDRESS_SERVER_URL);
for (int i = 0; i < 3 && domainAddresses.isEmpty(); ++i) {
getServersTask.run();
try {
Thread.sleep(100L);
} catch (Exception e) {
}
}
if (domainAddresses.isEmpty()) {
log.error("DynamicHTTPHostProvider-0001|cannnot get zookeeper address");
throw new RuntimeException("fail to get zk-server serverlist! env:" + ADDRESS_SERVER_URL);
}
TimerService.scheduleWithFixedDelay(getServersTask, 0L, 30L, TimeUnit.SECONDS);
isStart = true;
}

在getServerListTask的线程中,去获取并解析地址

class GetServerListTask implements Runnable {
final String url; GetServerListTask(String url) {
this.url = url;
}
public void run() {
//获取服务器地址
List<String> result = getZkServerList();
updateIfChanged(result);
} private synchronized void updateIfChanged(List<String> result) {
//更新domainAddresses
}

备注

详细代码可以查看 https://github.com/wpr7280/zktest

设置ZooKeeper服务器地址列表源码解析及扩展的更多相关文章

  1. Android恢复出厂设置流程分析【Android源码解析十】

    最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程: 在setting-->备份与重置--->恢复出厂设置--->重置手机---> ...

  2. [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (2)

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (2) 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (2) 0x00 摘要 0x01 总体流程 ...

  3. [源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3) 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3) 0x00 摘要 0x01 回顾 0x0 ...

  4. [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (4)

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (4) 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (4) 0x00 摘要 0x01 总体流程 ...

  5. [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器 --(1)

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器 --(1) 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器 --(1) 0x00 摘要 0x01 背景 1.1 ...

  6. dubbo源码解析五 --- 集群容错架构设计与原理分析

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 博客园 Dubbo 入门之二 --- 项目结构解析 博客园 Dubbo 源码分析系列之 ...

  7. FutureTask 源码解析

    FutureTask 源码解析 版权声明:本文为本作者原创文章,转载请注明出处.感谢 码梦为生| 刘锟洋 的投稿 站在使用者的角度,future是一个经常在多线程环境下使用的Runnable,使用它的 ...

  8. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

  9. Spring-cloud & Netflix 源码解析:Eureka 服务注册发现接口 ****

    http://www.idouba.net/spring-cloud-source-eureka-client-api/?utm_source=tuicool&utm_medium=refer ...

随机推荐

  1. Java基础之路(一)下--引用数据类型之数组

    上次我们说了java的基础数据类型,今天我们就来说一下引用数据类型中的数组. 什么是数组 数组:存储在一个连续的内存块中的相同数据类型(引用数据类型)的元素集合. 数组中的每一个数据称之为数组元素,数 ...

  2. 本地计算机上的XXX服务启动后停止,某些服务在未由其它服务或程序使用时将自动停止

    创建WindowsService,以及安装和卸载网上的资料一搜一大堆,在这里就不再做演示,只说明下博主在工作中使用WindowsService服务出现的错误,以及最终的结局方案. 1.启动window ...

  3. MySQL学习分享-->查询-->查询的原理

    查询的原理 在一个查询中常包含下述子句: 1.select,2.distinct,3.join,4.on,5.from,6.where,7.having,8.group by,9.order by,1 ...

  4. Java集合学习笔记

      在Java中,我们经常听到Collections框架.Collection类以及Collections类.这三者名字相似,但是从概念上讲却是不同的.Collections框架泛指Java中用于存储 ...

  5. 1657: [Usaco2006 Mar]Mooo 奶牛的歌声

    1657: [Usaco2006 Mar]Mooo 奶牛的歌声 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 526  Solved: 365[Submi ...

  6. HTTP协议&SOCKET协议

    一. HTTP协议是什么? 我们在浏览器的地址栏里输入的网站地址叫做 URL(UniformResourceLocator,统一资源定位符).就像每家每户都有一个门牌地址一样,每个网页也都有一个Int ...

  7. DARK的锁链

    Description 无向图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边.Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由主要边构成的路径.另外,Dark ...

  8. RAC OCR盘故障导致的集群重启恢复

    一.事故说明 最近出现了一次OCR盘的故障导致Oracle集群件宕机的事故,后以独占模式启动集群,并使用ocr备份恢复了OCR文件以及重新设置了vote disk,然后关闭集群,重启成功. 因此在此处 ...

  9. 《用Python做HTTP接口测试》学习感悟

    机缘巧合之下,报名参加了阿奎老师发布在"好班长"的课程<用Python做HTTP接口测试>,报名费:15rmb,不到一杯咖啡钱,目前为止的状态:坚定不移的跟下去,自学+ ...

  10. UICollectionView 适配 iPhone 7 Plus

    UICollectionView 适配 iPhone 7 Plus 需求:在屏幕上水平放置 5 张正方形图片,每张图片的宽度相等,无缝隙排列铺满一个屏幕宽度. 看似很简单的需求.用 UICollect ...