zoukankan      html  css  js  c++  java
  • ZooKeeper 笔记(4) 实战应用之【消除单点故障】

    关键节点的单点故障(Single Point of Failure)在大型的架构中,往往是致命的。比如:SOA架构中,服务注册中心(Server Register)统一调度所有服务,如果这个节点挂了,基本上整个SOA架构也就崩溃了,另外hadoop 1.x/2.x中的namenode节点,这是hdfs的核心节点,如果namenode宕掉,hdfs也就废了。ZooKeeper的出现,很好的解决了这一难题,其核心原理如下:

    1. 关键节点的运行实例(或服务器),可以跑多个,这些实例中的数据完全是相同的(即:对等设计),每个实例启动后,向ZK注册一个临时顺序节点,比如 /core-servers/server0000001, /core-servers/server0000002 ... ,最后的顺序号是由ZK自动递增的

    2. 其它应用需要访问1中的核心服务器里,可以事先约定好,从ZK的这些临时节点中,挑选一个序号最小的节点,做为主服务器(即master)

    3. 当master宕掉时,超过一定的时间阈值,临时节点将由ZK自动删除,这样原来序列最小的节点也就没了,客户端应用按2中的约定找最小节点的服务器时,自动会找到原来次最小的节点,继续充为master(老大挂了,老二顶上),即实现了故障转换。如果原来出问题的master恢复了,重新加入ZK,由于顺序号是一直递增,重新加入后,它将做为备胎待命。

    示例代码如下:

    上面是类图,CoreServer类对应核心服务器,ClientServer类对应客户端应用服务器,SPOFTest为单元测试类

    CoreServer代码:

    package yjmyzz.test;
    
    import org.I0Itec.zkclient.ZkClient;
    
    
    public class CoreServer {
    
        private String hostName;
    
        public CoreServer(String hostName) {
            this.hostName = hostName;
        }
    
        public void start() {
            ZkClient zk = ZKUtil.getZkClient();
            if (!zk.exists(ZKUtil.CORE_SERVER_NODE_NAME)){
                zk.createPersistent(ZKUtil.CORE_SERVER_NODE_NAME);
            }
            zk.createEphemeralSequential(ZKUtil.CORE_SERVER_NODE_NAME + "/server", hostName);
            System.out.println(hostName + " is running...");
    
        }
    
        public String getHostName() {
            return hostName;
        }
    
    }
    

    ClientServer类:

    package yjmyzz.test;
    
    import org.I0Itec.zkclient.ZkClient;
    
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * Created by jimmy on 15/6/28.
     */
    public class ClientServer {
    
        private String getCoreServer() {
            ZkClient zk = ZKUtil.getZkClient();
            List<String> servers = ZKUtil.getZkClient().getChildren(ZKUtil.CORE_SERVER_NODE_NAME);
            if (servers.size() <= 0) {
                return null;
            }
            for (String s : servers) {
                System.out.println(s);
            }
            Object[] arr = servers.toArray();
            Arrays.sort(arr);
    
            String data = zk.readData(ZKUtil.CORE_SERVER_NODE_NAME + "/" + arr[0].toString());
            System.out.println("node:" + arr[0].toString() + ", data:" + data);
            return data;
        }
    
        public void run(){
            System.out.println("客户端应用运行中,正在调用:" + getCoreServer() + " 上的服务");
        }
    }
    

    SPOF测试类:

    package yjmyzz.test;
    
    import org.junit.Test;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by jimmy on 15/6/28.
     */
    public class SPOFTest {
    
        @Test
        public void startCoreServer1() throws InterruptedException {
    
            CoreServer server1 = new CoreServer("server1");
            server1.start();
    
            while (true) {
                TimeUnit.SECONDS.sleep(5);
            }
    
        }
    
        @Test
        public void startCoreServer2() throws InterruptedException {
    
            CoreServer server2 = new CoreServer("server2");
            server2.start();
    
            while (true) {
                TimeUnit.SECONDS.sleep(5);
            }
    
        }
    
    
    
    
        @Test
        public void testSPOF() throws InterruptedException {
            ClientServer clientServer = new ClientServer();
            clientServer.run();
    
            //此时,手动停止coreServer1
            TimeUnit.SECONDS.sleep(60);
    
            //再次运行
            clientServer.run();
    
        }
    
    
    }
    

    测试步骤:

    1. 先启用startCoreServer1()、startCoreServer2() 由于这二个方法中,最后用死循环阻止了程序退出,所以这二台server会一直运行下去,除非手动kill 进程

    2. 再启用testSPOF(),在45行这里可以打个断点,进入断点时,可以手动把startCoreServer1()对应的进程kill掉,即:模拟server1挂掉,然后继续执行,观察输出。

    运行结果:

    zookeeper state changed (SyncConnected)
    server0000000007
    server0000000006
    node:server0000000006, data:server1
    客户端应用运行中,正在调用:server1 上的服务
    ...
    zookeeper state changed (SyncConnected)
    server0000000007
    Disconnected from the target VM, address: '127.0.0.1:64788', transport: 'socket'
    node:server0000000007, data:server2
    客户端应用运行中,正在调用:server2 上的服务

    -------------

    从测试结果看,客户端访问的核心服务器,自动从server1切换到了server2上。

      

  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/Solve-the-problem-of-single-point-of-failure-using-ZooKeeper.html
Copyright © 2011-2022 走看看