zookeeper-3.4.x 动态服务器上下线(代码)

创建maven工程

略

idea创建maven工程必须修改idea配置

pom.xml

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.8</version>
</dependency>

log4j.properties

打印 hadoop debug 信息

在 resources 文件夹下创建 log4j.properties 文件,内容如下:

log4j.rootLogger=INFO, stdout 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n 
log4j.appender.logfile=org.apache.log4j.FileAppender 
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout 
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

java

ZkUtil

zookeeper工具类,方便连接 zookeeper、注册节点

package std;

import java.io.IOException;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class ZkUtil {
    private static String connectString = "hadoop1:2181,hadoop2:2181,hadoop3:2181";
    private static int sessionTimeout = 2000;
    //根节点名
    private static String ROOT_NODE="/myserver";
    // 服务名
    private static String SERVICE_NAME="notice";

    private ZooKeeper zk = null;

    // 创建到 zk 的客户端连接
    public void connect() throws IOException {
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {

            }
        });
    }

    // 注册服务器
    public void regist(String nodeData) throws Exception {
        //判断根节点是否存在,false表示不需要监听
        Stat stat = zk.exists(ROOT_NODE, false);
        if(stat==null){//不存在就创建
            zk.create(
                    ROOT_NODE, //节点路径
                    null, //节点数据
                    Ids.OPEN_ACL_UNSAFE, //节点权限
                    CreateMode.PERSISTENT //持久化目录节点
            );
        }
        //创建子节点
        String res = zk.create(
                ROOT_NODE+"/"+SERVICE_NAME, //节点路径
                nodeData.getBytes(), //节点数据
                Ids.OPEN_ACL_UNSAFE, //节点权限
                CreateMode.EPHEMERAL_SEQUENTIAL //临时顺序编号目录节点,由zk进行顺序编号,且断开后,该节点被删除
        );
        System.out.println("节点:"+res);
    }

}

notice1

模拟 notice1

package std;

public class NoticeService1 {
    public static void main(String[] args) throws Exception {
        String data="hadoop1:8080";
        ZkUtil zk = new ZkUtil();
        zk.connect();
        zk.regist(data);

        System.out.println(data+" 启动成功!");
        //休眠,否则退出程序,由于创建的是临时节点,会自动删除节点
        Thread.sleep(1000000);
    }
}

notice2

package std;

public class NoticeService2 {
    public static void main(String[] args) throws Exception {
        String data="hadoop2:8080";
        ZkUtil zk = new ZkUtil();
        zk.connect();
        zk.regist(data);

        System.out.println(data+" 启动成功!");
        Thread.sleep(1000000);//休眠,否则退出程序
    }

}

notice3

package std;

public class NoticeService3 {
    public static void main(String[] args) throws Exception {
        String data="hadoop3:8080";
        ZkUtil zk = new ZkUtil();
        zk.connect();
        zk.regist(data);

        System.out.println(data+" 启动成功!");
        Thread.sleep(1000000);//休眠,否则退出程序
    }

}

GuanzhuService

启动后,向 zookeeper 发请求,获取服务器列表,并注册监听

package std;


import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.util.List;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class GuanzhuService {
    private static String connectString = "hadoop1:2181,hadoop2:2181,hadoop3:2181";
    private static int sessionTimeout = 2000;
    private ZooKeeper zk = null;
    // 根节点名
    private static String ROOT_NODE = "/myserver";

    // 创建到 zk 的客户端连接
    public void connect() throws IOException {
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    LocalTime time= LocalTime.now();
                    System.out.println("监听开始:==============="+time);
                    getServers();
                    System.out.println("监听结束===============\n\n\n");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }

    // 获取服务器信息
    public void getServers() throws Exception {
        // 获取子节点信息,true表示对节点进行监听
        List<String> children = zk.getChildren(ROOT_NODE, true);
        // 遍历所有节点,获取节点中的数据
        for (String child : children) {
            byte[] data = zk.getData(ROOT_NODE + "/" + child, false, null);
            System.out.println("notice微服务:"+new String(data));
        }
        System.out.println("=====");
    }

    public static void main(String[] args) throws Exception {
        GuanzhuService service = new GuanzhuService();
        service.connect();
        // ????必须调用下面方法,否则 connect() 方法中的 getServers() 不会执行
        // service.getServers();
        // 休眠,否则退出程序,退出后,无法监听
        Thread.sleep(1000000);//休眠,否则退出程序
    }
}

启动

先启动 notice1、notice2、notice3

最后启动 GuanzhuService,启动后,读取 notice 列表信息

测试 notice3 下线

停止 notice3,zk会删除相应的节点数据,并向 GuanzhuService 发送新的节点数据

测试 notice3 上线

再次启动 notice3,向 zk 写入节点数据,zk向 GuanzhuService 发送新的节点数据


原文出处:/show_1IX2APaunzPA.html