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. Java进阶7 并发优化2 并行程序设计模式

    Java进阶7 并发优化2 并行程序设计模式20131114 1.Master-worker模式 前面讲解了Future模式,并且使用了简单的FutureTask来实现并发中的Future模式.下面介 ...

  2. C++多线程1.createthread

    C++ 多线程知识1.多线程入门 CreateThread 20131021 1.介绍WinAPI中的CreateThread 函数原型: HANDLE WINAPI CreateThread( LP ...

  3. eureka-4-eureka server 高可用

    Eureka Server 可以通过运行多个实例并相互注册实现高可用部署.Eureka Server 实例之间会彼此增量同步信息,确保所有节点信息一致. 关键点: 配置: eureka.client. ...

  4. JBPM4入门——2.在eclipse中安装绘制jbpm流程图的插件

    本博文只是简要对JBPM4进行介绍,如需更详细内容请自行google 链接: JBPM入门系列文章: JBPM4入门——1.jbpm简要介绍 JBPM4入门——2.在eclipse中安装绘制jbpm流 ...

  5. New Concept English three (23)

    31w 45 People become quite illogical when they try to decide what can be eaten and what cannot be ea ...

  6. svn 图标状态说明

    http://blog.csdn.net/coslay/article/details/41980131

  7. js获取来源网址

    举例: 1. a.html文件内容如下: <a href="b.html">浏览b.html </a> 2. b.html文件中的内容如下: <bod ...

  8. C#项目中怎样创建和使用类和类库

    创建一个类库项目在“文件”菜单上,选择“新建项目”. 在“新建项目”对话框的“模板”窗格中,单击“类库”. 在“名称”框中键入 Persons,再单击“确定”. 把“添加新解决方案”勾选掉,选择“添入 ...

  9. iOS开发之解决WebView自适应内容高度

    这段时间写的项目中,有涉及到根据后端上传的表单内容,然后在移动端将内容排版重新展示的功能点,所以小小的写一下解决办法. 首先如果直接进行内容展示,或者进行sizeToFit的操作,那么可能会造成图片超 ...

  10. Postfix常用命令和邮件队列管理(queue)

    本文主要介绍一下postfix的常用命令及邮件队列的管理: Postfix有以下四种邮件队列,均由管理队列的进程统一进行管理: maildrop:本地邮件放置在maildrop中,同时也被拷贝到inc ...