Zookeeper--集群管理

在多台服务器组成的集群中,需要监控每台服务器的状态,一旦某台服务器挂掉了或有新的机器加入集群,集群都要感知到,从而采取相应的措施。一个主动的集群可以自动感知节点的死亡和新节点的加入,它才对更高效的提供服务。通常的做法是有台主机器定时的去获取其他机器的心跳,或其他机器定时主动汇报自己的状态,这种方式存在一定的延时,并且主机器成为单点,一旦挂掉便影响整个集群。

使用Zookeeper可以方便的实现集群管理的功能。思路如下,每个服务器启动时都向zk服务器提出创建临时节点的请求,并且使用getChildren设置父节点的观察,当该服务器挂掉之后,它创建的临时节点也被Zookeeper服务器删除,然后会触发监视器,其他服务器便得到通知。创建新节点也是同理。

并且利用Zookeeper的Leader选举功能可以选出服务中的一台作为Leader,在比如任务调度类似的场景中有用。

下面是一个简单的模拟:

ServerUnit模拟在不同机器上启动的服务,启动时向Zookeeper服务器注册自己,并保存自己的IP和端口;实现CallBack接口:在其他节点发生变化时执行的逻辑

public class ServerUnit {

    public static final String SER_NAME = "ServerUnit";

    public static void main(String[] args) throws InterruptedException, IOException, KeeperException {

        System.out.println("begin register to Zookeeper..");

        String address = IPUtil.getLoaclIP() + ":" + new Random().nextInt(255);

        ServiceMng mng = new ServiceMng(SER_NAME);

        String serverId = mng.register(address, new CallBack<ServiceMng.ChildrenChangedResult>() {
@Override
public void callback(ServiceMng.ChildrenChangedResult cn) throws KeeperException, InterruptedException {
for (String str : cn.getUp()) {
System.out.println("检测到服务加入: " + mng.queryAddress(str));
}
for (String str : cn.getDown()) {
System.out.println("检测到服务退出: " + mng.queryAddress(str));
}
}
}); System.out.println("ServerUnit started at: " + address);
TimeUnit.HOURS.sleep(1);
}
}

---

CallBack接口:

public interface CallBack<T> {

    void callback(T t) throws Exception;

}

---

ServerMng 提供向Zookeeper注册服务和获取服务等方法,被服务单元依赖

public class ServiceMng {

    private static final String APPS_PATH = "/__apps__";
private String serviceName;
private ZooKeeper zk;
private CountDownLatch latch = new CountDownLatch(1);
private List<String> serList;
private Map<String, String> serMap = new HashMap<>(); ServiceMng(String serviceName) {
this.serviceName = serviceName;
} public String register(String address, CallBack callback) throws KeeperException, InterruptedException, IOException {
if (zk != null) {
throw new IllegalArgumentException("method should not invoke twice.");
} zk = new ZooKeeper("localhost", 30000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
latch.countDown();
}
if (watchedEvent.getType() == Watcher.Event.EventType.NodeChildrenChanged) {
try {
List list = zk.getChildren(APPS_PATH + "/" + serviceName, true);
refresh(list);
callback.callback(new ChildrenChangedResult(list, serList));
serList = list;
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}); latch.await();
if (zk.exists(APPS_PATH, false) == null) {
zk.create(APPS_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
if (zk.exists(APPS_PATH + "/" + serviceName, false) == null) {
zk.create(APPS_PATH + "/" + serviceName, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} String path = zk.create(APPS_PATH + "/" + serviceName + "/", address.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
List list = zk.getChildren(APPS_PATH + "/" + serviceName, true);
refresh(list);
serList = list;
return path;
} private void refresh(List<String> paths) throws KeeperException, InterruptedException {
for (String path : paths) {
byte[] b = zk.getData(APPS_PATH + "/" + serviceName + "/" + path, false, null);
serMap.put(path, new String(b));
}
} public String queryLeaderIp(String serviceName) throws KeeperException, InterruptedException {
List<String> apps = zk.getChildren(APPS_PATH + "/" + serviceName, false);
if (apps.isEmpty()) {
return null;
}
Collections.sort(apps);
byte[] data = zk.getData(apps.get(0), false, null);
return new String(data);
} public String queryRandomServerIp(String serviceName) throws KeeperException, InterruptedException {
List<String> apps = zk.getChildren(APPS_PATH + "/" + serviceName, false);
if (apps.isEmpty()) {
return null;
}
Random r = new Random();
byte[] data = zk.getData(apps.get(r.nextInt(apps.size())), false, null);
return new String(data);
} public String queryAddress(String path) {
return serMap.get(path);
} public static class ChildrenChangedResult {
List<String> up = null;
List<String> down = null; ChildrenChangedResult(List now, List last) {
up = new LinkedList(now);
up.removeAll(last);
down = new LinkedList(last);
down.removeAll(now);
} public List<String> getUp() {
return up;
} public List<String> getDown() {
return down;
}
} }

---

依次启动3个ServerUnit,查看控制台:

  

依次关闭2个ServerUnit,查看控制台:

 

从关闭ServerUnit到控制台打印退出大概延迟8s左右,配置zk的tickTime=1000,比预期的要慢一些。

end

Zookeeper--集群管理的更多相关文章

  1. 【拆分版】Docker-compose构建Zookeeper集群管理Kafka集群

    写在前边 在搭建Logstash多节点之前,想到就算先搭好Logstash启动会因为日志无法连接到Kafka Brokers而无限重试,所以这里先构建下Zookeeper集群管理的Kafka集群. 众 ...

  2. solr集群搭建,zookeeper集群管理

    1. 第一步 把solrhome中的配置文件上传到zookeeper集群.使用zookeeper的客户端上传. 客户端命令位置:/root/solr-4.10.3/example/scripts/cl ...

  3. 大数据学习路线:Zookeeper集群管理与选举

    大数据技术的学习,逐渐成为很多程序员的必修课,因为趋势也是因为自己的职业生涯.在各个技术社区分享交流成为很多人学习的方式,今天很荣幸给我们分享一些大数据基础知识,大家可以一起学习! 1.集群机器监控 ...

  4. zookeeper集群管理配置优化总结

    1:默认jvm没有配置Xmx.Xms等信息,可以在conf目录下创建java.env文件 export JVMFLAGS="-Xms512m -Xmx512m $JVMFLAGS" ...

  5. zookeeper安装和应用场合(名字,配置,锁,队列,集群管理)

    安装和配置详解 本文介绍的 Zookeeper 是以 3.2.2 这个稳定版本为基础,最新的版本可以通过官网http://hadoop.apache.org/zookeeper/ 来获取,Zookee ...

  6. 2 weekend110的zookeeper的原理、特性、数据模型、节点、角色、顺序号、读写机制、保证、API接口、ACL、选举、 + 应用场景:统一命名服务、配置管理、集群管理、共享锁、队列管理

    在hadoop生态圈里,很多地方都需zookeeper. 启动的时候,都是普通的server,但在启动过程中,通过一个特定的选举机制,选出一个leader. 只运行在一台服务器上,适合测试环境:Zoo ...

  7. 一步到位分布式开发Zookeeper实现集群管理

    说到分布式开发Zookeeper是必须了解和掌握的,分布式消息服务kafka .hbase 到hadoop等分布式大数据处理都会用到Zookeeper,所以在此将Zookeeper作为基础来讲解. Z ...

  8. zookeeper配置管理+集群管理实战

    引言 之前就了解过kafka,看的似懂非懂,最近项目组中引入了kafka,刚好接着这个机会再次学习下. Kafka在很多公司被用作分布式高性能消息队列,kafka之前我只用过redis的list来做简 ...

  9. 基于zookeeper+mesos+marathon的docker集群管理平台

    参考文档: mesos:http://mesos.apache.org/ mesosphere社区版:https://github.com/mesosphere/open-docs mesospher ...

  10. 搞懂分布式技术5:Zookeeper的配置与集群管理实战

    搞懂分布式技术5:Zookeeper的配置与集群管理实战 4.1 配置文件 ZooKeeper安装好之后,在安装目录的conf文件夹下可以找到一个名为“zoo_sample.cfg”的文件,是ZooK ...

随机推荐

  1. 【fzu-2261】浪里个浪

    TonyY是一个喜欢到处浪的男人,他的梦想是带着兰兰姐姐浪遍天朝的各个角落,不过在此之前,他需要做好规划. 现在他的手上有一份天朝地图,上面有n个城市,m条交通路径,每条交通路径都是单行道.他已经预先 ...

  2. C语言学习之指针

    指针这块,看了好久才有点头绪,稍微有点理解了. 一.指针申明以及赋值 int *p; 这样就声明了一个int型的指针p,这个p就是指针变量,可能上述的书写方式会混淆我们队指针的理解(*号) 我们可以这 ...

  3. Shell 循环中实现展示进度百分比的脚本方法

    Shell 循环中实现展示进度百分比的脚本方法 当我需要处理一个几万行的文件的时候,需要处理的时间是比较长的.我一开始的想法是,没处理一行,就输出一个 # 号.但是这样还是会出现很多很多的 # 号,即 ...

  4. 深度学习(六十九)darknet 实现实验 Compressing Deep Neural Networks with Pruning, Trained Quantization and Huffma

    本文主要实验文献文献<Deep Compression: Compressing Deep Neural Networks with Pruning, Trained Quantization ...

  5. 【剑指offer】圆圈中最后剩下的数字(约瑟夫问题),C++实现

    原创博文,转载请注明出处! # 题目 # 思路 本题即为典型的约瑟夫问题,通过递推公式倒推出问题的解.原始问题是从n个人中每隔m个数踢出一个人,原始问题变成从n-1个人中每隔m个数踢出一个人--    ...

  6. TreeSet中自定义Comparator实现降序

    @Test public void test1() { TreeSet ts = new TreeSet<Integer>(new MyComparator()); ts.add(3); ...

  7. [转]redis服务器与客户端保活参数(tcp-keepalive)设置

    最近使用redis的list做跨进程的消息队列,客户端使用的是redis-cplusplus-client.这个client库还是蛮好用的,提供了和redis命令行一致的接口,很方便. 使用过程中发现 ...

  8. 很让人受教的提高php代码质量的方法

    1.不要使用相对路径 常常会看到: require_once('../../lib/some_class.php'); 该方法有很多缺点: 它首先查找指定的php包含路径, 然后查找当前目录. 因此会 ...

  9. HDU2157 How many ways矩阵再识

    春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, 葱头决定, 每次上课都走不同的路线去教室 ...

  10. hiho1613 墨水滴

    对不起,太弱了.................想了一下午