通常zookeeper在分布式服务中作为注册中心,实际上它还可以办到很多事。比如分布式队列、分布式锁

由于公司服务中有很多定时任务,而这些定时任务由于一些历史原因暂时不能改造成框架调用

于是想到用zookeeper特性来实现

首先我们先了解下zk工作原理

结构图解释:左侧树状结构为zookeeper集群,右侧为程序服务器。所有的服务器在启动的时候,都会订阅zookeeper中master节点的删除事件,以便在主服务器挂掉的时候进行抢主操作;所有服务器同时会在servers节点下注册一个临时节点(保存自己的基本信息),以便于应用程序读取当前可用的服务器列表。

选主原理介绍:zookeeper的节点有两种类型,持久节点跟临时节点。临时节点有个特性,就是如果注册这个节点的机器失去连接(通常是宕机),那么这个节点会被zookeeper删除。选主过程就是利用这个特性,在服务器启动的时候,去zookeeper特定的一个目录下注册一个临时节点(这个节点作为master,谁注册了这个节点谁就是master),注册的时候,如果发现该节点已经存在,则说明已经有别的服务器注册了(也就是有别的服务器已经抢主成功),那么当前服务器只能放弃抢主,作为从机存在。同时,抢主失败的当前服务器需要订阅该临时节点的删除事件,以便该节点删除时(也就是注册该节点的服务器宕机了或者网络断了之类的)进行再次抢主操作。从机具体需要去哪里注册服务器列表的临时节点,节点保存什么信息,根据具体的业务不同自行约定。选主的过程,其实就是简单的争抢在zookeeper注册临时节点的操作,谁注册了约定的临时节点,谁就是master。

到此我们就可以着手实现了

 public class ZkMasterChooseUtil {

     public static final Map<String,ZkClient > map = new ConcurrentHashMap<>();
public static final Map<String,String > pathMap = new ConcurrentHashMap<>();
public static final Map<String,List<String>> childMap = new ConcurrentHashMap<>(); public static final String IP = getServerIp(); public static final boolean isMaster(String zkServer,String path){ try {
if (!map.containsKey(zkServer)){
reconnect(zkServer);
}
}catch (Exception e){
reconnect(zkServer);
}
String seq = null;
if (!pathMap.containsKey(path)){
if (!map.get(zkServer).exists(path)){
map.get(zkServer).createPersistent(path,true);
}
map.get(zkServer).subscribeChildChanges(path, (parentPath, currentChilds) -> {
childMap.put(parentPath,resetList(currentChilds != null? currentChilds : new ArrayList<>()));
});
pathMap.remove(path);
seq = map.get(zkServer).createEphemeralSequential(path+"/",IP);
pathMap.put(path,seq);
List<String> list = map.get(zkServer).getChildren(path);
childMap.put(path,resetList(list != null ? list : new ArrayList<>()));
}
seq = pathMap.get(path);
List<String> list = childMap.get(path);
if(list.size()>0){
if ((path+"/"+list.get(0)).equals(seq)){
return true;
}
System.out.println("path = "+(path+"/"+list.get(0)) +" seq = "+seq);
}
return false;
} private static void reconnect(String zkServer){
ZkClient zkClient = new ZkClient(new ZkConnection(zkServer,10000),10000);
map.put(zkServer,zkClient);
} private static String getServerIp() {
try {
InetAddress i = getLocalHostLANAddress();
return i != null ? i.getHostAddress() : null;
} catch (Exception e) {
e.printStackTrace();
}
return "";
} public static InetAddress getLocalHostLANAddress() {
try {
InetAddress candidateAddress = null;
// 遍历所有的网络接口
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
// 在所有的接口下再遍历IP
for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
// 排除loopback类型地址
if (!inetAddr.isLoopbackAddress()) {
if (inetAddr.isSiteLocalAddress()) {
// 如果是site-local地址,就是它了
return inetAddr;
} else if (candidateAddress == null) {
// site-local类型的地址未被发现,先记录候选地址
candidateAddress = inetAddr;
}
}
}
}
if (candidateAddress != null) {
return candidateAddress;
}
// 如果没有发现 non-loopback地址.只能用最次选的方案
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
return jdkSuppliedAddress;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} private static List<String> resetList(List<String> list){
if (list.size() == 0){
return list;
}
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Long l1 = Long.valueOf(o1.substring(o1.lastIndexOf("/")+1));
Long l2 = Long.valueOf(o2.substring(o2.lastIndexOf("/")+1));
return l1.compareTo(l2);
}
});
return list;
} }

注:传入path即为要抢注的节点

zookeeper分布式服务中选主的应用的更多相关文章

  1. Hadoop Zookeeper 分布式服务框架

    what is Zookeeper? 1,开源的分布式的,为分布式应用提供协调服务的Apache项目2,提供一个简单原语集合,以便于分布式应用可以在它之上构建更高层次的同步服务3,设计非常易于编程,它 ...

  2. Zookeeper分布式服务协调组件

    1.简介 Zookeeper是一个分布式服务协调组件,是Hadoop.Hbase.Kafka的重要组件,它是一个为分布式应用提供一致性服务的组件.   Zookeeper的目标就是封装好复杂易出错的服 ...

  3. Java学习之Dubbo+ZooKeeper分布式服务Demo

    背景:在之前的一个<Java学习之SpringBoot整合SSM Demo>分享中说到搭建ZooKeeper和Dubbo分布式框架中遇到了一些技术问题没能成功,只分享了其中的一个中间产物, ...

  4. 分布式服务框架Zookeeper

    协议介绍 zookeeper协议分为两种模式 崩溃恢复模式和消息广播模式 崩溃恢复协议是在集群中所选举的leader 宕机或者关闭 等现象出现 follower重新进行选举出新的leader 同时集群 ...

  5. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据

    转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html Zookeeper 分布式服务框架是 Apa ...

  6. 分布式服务框架 Zookeeper(转)

    分布式服务框架 Zookeeper -- 管理分布式环境中的数据 Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题 ...

  7. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据(转载)

    本文转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Had ...

  8. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载

    原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Hadoop ...

  9. 分布式服务框架 Zookeeper — 管理分布式环境中的数据

    本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们理解. ...

随机推荐

  1. springBoot 项目war包部署及改为war包后资源路径错误问题

    参考资料: https://blog.csdn.net/rico_zhou/article/details/83415114 https://blog.csdn.net/pz641/article/d ...

  2. efk学习整理

    概念 Logstash 数据收集处理引擎.支持动态的从各种数据源搜集数据,并对数据进行过滤.分析.丰富.统一格式等操作,然后存储以供后续使用. kibana 可视化化平台.它能够搜索.展示存储在 El ...

  3. python日志模块的使用

    学习一下python的日志模块logging,可以参考如下博客,写得很详细 https://www.cnblogs.com/yyds/p/6901864.html https://www.cnblog ...

  4. Docker镜像加速器配置

    一.为什么要配置Docker镜像加速器 因为我们默认pull的docker镜像是从Docker Hub来下载,由于其服务器在国外,速度会比较慢.因此我们可以配置成国内的镜像仓库,这样可以加速镜像的上传 ...

  5. c代码写数据到二进制的bin文件中

    需要将数据写入到bin文件中,打开该文件是一堆乱码,增加数据的保密性 例如:要写入的数据为一个字符串,加上若干个int型整数 #define _CRT_SECURE_NO_WARNINGS #incl ...

  6. Mac安装python3.x+pycharm+elasticsearch+常见报错处理(1)

    ---恢复内容开始--- mac安装python有两种方式:此处叙述官网安装下载. mac 自带python2.x版本,python2和3之间的差距还是有的.下面简单叙述我安装python3.7的过程 ...

  7. Java核心技术卷一 · 笔记(2)

    目录 1.多态.动态绑定 2.覆盖 3.阻止继承:final 类和方法 4.抽象类(abstract修饰) 5. 4 个访问修饰符: 6.toString() 7.对设计继承关系很有帮助的建议 8.接 ...

  8. ubuntu nginx ssl 证书配置

      前几天自己用 egg.js 写了个 api 接口,然后把它部署到服务器上.服务器是ubuntu 16.04 + nginx:因为要用到https,然后今天实践了一下如何配置https. 关于htt ...

  9. hive -- 分区,分桶(创建,修改,删除)

    hive -- 分区,分桶(创建,修改,删除) 分区: 静态创建分区: 1. 数据: john doe 10000.0 mary smith 8000.0 todd jones 7000.0 boss ...

  10. [转]imageMagick 在nodejs中报错Error: spawn identify ENOENT的解决方案

    同时还有 Error: Could not execute GraphicsMagick/ImageMagick 这个问题, 也参考了 https://blog.csdn.net/chenxinpen ...