zookeeper实现分布式应用系统服务器上下线动态感知程序、监听机制与守护线程

简介: zookeeper实现分布式应用系统服务器上下线动态感知程序、监听机制与守护线程

需求


在分布式系统中存在多个服务器,这些服务器可以动态上下线,而客户端可以连接任意服务器,但是如果连接的服务器突然下线那么客户端需要重新连接其他服务器,这就需要在服务器上下线的时候客户端能感知,获取哪些可以连接的服务器。


解决思路


每次服务器启动的时候去zookeeper上进行注册(注册规则自由指定,比如简单使用/servers/server001 hostname),而客户端上线就获取服务器列表,并对节点进行监听,一旦有服务器下线那么就能监听到事件从而重新获取服务器列表。

image.png


程序简单实现

服务器端:

/**
 * 服务端程序
 * @author
 *
 */
public class DistributedServer {
    private static final String connectionString = "192.168.47.141:2181";
    public static final Integer sessionTimeout = 2000;
    public static ZooKeeper zkClient = null;
    /**
     * 获取zookeeper连接
     * @throws Exception
     */
    public void getConnection() throws Exception{
        zkClient = new ZooKeeper(connectionString, sessionTimeout, new Watcher(){
            //收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)
            public void process(WatchedEvent event) {
                System.out.println(event.getType()+","+event.getPath());
                try {
                    //为了能一直监听,调用一次注册一次
                    zkClient.getChildren("/", true);
                }catch(Exception e){
                }
            }});
    }
    /**
     * 注册服务器信息
     * @param hostname 注册的服务器名
     * @throws Exception
     */
    public void registerServer(String hostname) throws Exception{
        //创建的是带序号的临时节点 生成的节点像/servers/server000001,/servers/server000002等
        //节点数据即为注册的主机名
        String path = zkClient.create("/server", hostname.getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(hostname+" --上线了-- "+path);
    }
    /**
     * 服务器注册完后,执行业务逻辑
     * @param hostname
     * @throws IOException
     */
    public void executeBusiness(String hostname) throws IOException {
        System.out.println(hostname+"开始工作了!");
        System.in.read();
    }
    public static void main(String[] args) throws Exception {
        //获取zookeeper连接
        DistributedServer server = new DistributedServer();
        server.getConnection();
        //服务器上线,完成注册
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入hostname");
        String hostname = scanner.nextLine();
        server.registerServer(hostname);
        //执行业务逻辑
        server.executeBusiness(hostname);
    }
}

客户端:

/*
 * 客户端程序
 */
public class DistributeClient {
    private static final String connectionString = "192.168.47.141:2181";
    public static final Integer sessionTimeout = 2000;
    public static ZooKeeper zkClient = null;
    public static final String parentNode = "/";
    //注意:加volatile的意义何在?使得多线程看到的服务器列表一致而不会拷贝到自己的工作空间
    public volatile List<String> serverList = new ArrayList<String>();
    /**
     * 获取zookeeper连接
     * @throws Exception
     */
    public void getConnection() throws Exception{
        zkClient = new ZooKeeper(connectionString, sessionTimeout, new Watcher(){
            //收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)
            public void process(WatchedEvent event) {
                System.out.println(event.getType()+","+event.getPath());
                try {
                    //重新获取(更新)服务器列表,并进行监听
                    getServerList();
                }catch(Exception e){
                }
            }});
    }
    /**
     * 获取服务器列表信息,并对父节点进行监听
     * @throws Exception
     */
    public void getServerList() throws Exception{
        //获取服务器列表,并对父节点进行监听
        //getChildren()相对于命令行 ls /znode,对子节点进行监听
        List<String> children = zkClient.getChildren(parentNode, true);
        //创建临时集合,将子节点存入
        List<String> childrenList = new ArrayList<String>();
        for (String child : children) {
            byte[] data = zkClient.getData(parentNode+child, false, null);
            childrenList.add(new String(data));
        }
        //将临时集合中的节点赋给服务器列表serverList,以便业务线程使用
        serverList = childrenList;
        System.out.println(serverList);
    }
    /**
     * 业务功能
     * @throws Exception
     */
    public void executeBusiness() throws Exception{
        System.out.println("获取的服务器列表:"+serverList);
        System.out.println("客户端开始工作了...");
        System.in.read();
    }
    public static void main(String[] args) throws Exception {
        //获取zookeeper连接
        DistributeClient client = new DistributeClient();
        client.getConnection();
        //获取服务器列表
        client.getServerList();
        //业务功能
        client.executeBusiness();
    }
}

测试

运行三次服务器端程序,输入的hostname分别为mini1,mini2,mini3当成注册了三个服务器


image.png

image.png



运行客户端程序(可以启动多次,简单起见这里就一次)


image.png


关闭其中2个(mini1,mini2)连接zookeeper的客户端(关闭后注册的服务器也就消失了),查看客户端输出


image.png


一旦服务器下线了,客户端能监听到并且重新获取服务器列表。


目录
相关文章
|
11月前
|
安全 JavaScript 前端开发
HarmonyOS NEXT~HarmonyOS 语言仓颉:下一代分布式开发语言的技术解析与应用实践
HarmonyOS语言仓颉是华为专为HarmonyOS生态系统设计的新型编程语言,旨在解决分布式环境下的开发挑战。它以“编码创造”为理念,具备分布式原生、高性能与高效率、安全可靠三大核心特性。仓颉语言通过内置分布式能力简化跨设备开发,提供统一的编程模型和开发体验。文章从语言基础、关键特性、开发实践及未来展望四个方面剖析其技术优势,助力开发者掌握这一新兴工具,构建全场景分布式应用。
968 35
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
315 2
|
10月前
|
分布式计算 Java 大数据
Java 大视界 —— 基于 Java 的大数据分布式计算在气象数据处理与天气预报中的应用进展(176)
本文围绕基于 Java 的大数据分布式计算在气象数据处理与天气预报中的应用展开,剖析行业现状与挑战,阐释技术原理,介绍其在数据处理及天气预报中的具体应用,并结合实际案例展示实施效果。
Java 大视界 -- 基于 Java 的大数据分布式存储在视频监控数据管理中的应用优化(170)
本文围绕基于 Java 的大数据分布式存储在视频监控数据管理中的应用展开,分析管理现状与挑战,阐述技术应用,结合案例和代码给出实操方案。
|
机器学习/深度学习 存储
DeepSeek进阶开发与应用4:DeepSeek中的分布式训练技术
随着深度学习模型和数据集规模的扩大,单机训练已无法满足需求,分布式训练技术应运而生。DeepSeek框架支持数据并行和模型并行两种模式,通过将计算任务分配到多个节点上并行执行,显著提高训练效率。本文介绍DeepSeek中的分布式训练技术,包括配置与启动方法,帮助用户轻松实现大规模模型训练。数据并行通过`MirroredStrategy`同步梯度,适用于大多数模型;模型并行则通过`ParameterServerStrategy`异步处理大模型。DeepSeek简化了分布式环境配置,支持单机多卡和多机多卡等场景。
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
318 5
|
Dubbo 应用服务中间件 Apache
Dubbo 应用切换 ZooKeeper 注册中心实例,流量无损迁移
如果 Dubbo 应用使用 ZooKeeper 作为注册中心,现在需要切换到新的 ZooKeeper 实例,如何做到流量无损?
256 4
|
分布式计算 Hadoop
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
313 1
|
分布式计算 监控 Hadoop
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
302 1