设为首页 收藏本站
查看: 663|回复: 0

[经验分享] zookeeper学习笔记二

[复制链接]

尚未签到

发表于 2017-4-19 09:40:36 | 显示全部楼层 |阅读模式
  这几天尝试进行leader/follower的测试,当然目前还没去看源码实现.但觉得还是相当的.
  以下是对网上一段代码的修改,因为原来的测不出来什么东西.
  note:
  运行时只有两个节点时(leader&follower),当leader down后,the other one 一般很少自动切换到ld;但三个以上是没有问题的,何解?不知道是不是所谓的'ensemble'模式下'大部分机器正常动作才提供supply services这个原因呢...

  
/**
 * LeaderElection
 * 通用实现方案:(MY)
 * 假如这个最小编号的 Server 死去,**由于是 EPHEMERAL 节点,死去的 Server 对应的节点也被删除**,
 * 所以当前的节点列表中又出现一个最小编号的节点,我们就选择这个节点为当前 Master。
 * 这样就实现了动态选择 Master,避免了传统意义上单 Master 容易出现单点故障的问题。(可以参考本项目Locks.java)
 * NOTE:这里的实现是简化的
 * 
 * 本测试需要先单独启动TestMainServer(也可以打开TestMainServer.start()再启clients RAW),
 *  然后再启动其它若干个,
 *  再手工删除master node:/GroupMembers/leader,
 * 观察其它节目是否可以顺利过渡到新的leader-followers状态.

 */
public class LeaderElection extends TestMainClient {
    public static final Logger logger = Logger.getLogger(LeaderElection.class);
 
    public LeaderElection(String connectString, String root) {
        super(connectString);
//        try {
//            connectedSignal.await();    //MY test result:no effect
//        } catch (InterruptedException e1) {
//            e1.printStackTrace();
//        }     
         
        this.root = root;
        if (zk != null) {
            try {
                Stat s = zk.exists(root, false);
                if (s == null) {
                    zk.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                }
            } catch (KeeperException e) {
                logger.error(e);
            } catch (InterruptedException e) {
                logger.error(e);
            }
        }
    }
 
    void findLeader() throws InterruptedException, UnknownHostException, KeeperException {
        byte[] leader = null;
        try {
            leader = zk.getData(root + "/leader", true, null);
        } catch (KeeperException e) {
            if (e instanceof KeeperException.NoNodeException) {    //this exception is acceptable
                logger.error(e);
                e.printStackTrace();
            } else {
                throw e;
            }
        }
        //已经存在master,只能作为follower
        if (leader != null) {
            System.out.println("10");
            following();
            //MY
            synchronized(mutex){
                mutex.wait();
            }
            System.out.println("14");
            findLeader();    //继续竟争master
        } else {
            System.out.println("11");
            String newLeader = null;
            byte[] localhost = InetAddress.getLocalHost().getAddress();
            try {
                newLeader = zk.create(root + "/leader", localhost, ZooDefs.Ids.OPEN_ACL_UNSAFE, 
                        CreateMode.EPHEMERAL);    //NOTE: 必须为临时节点,server死亡后可以由其它节点实时选举leader
                zk.exists(root + "/leader", true);    //set a watch for the COMING leader!
                
            } catch (KeeperException e) {
                //并发运行时可能出现此情况,this exception is acceptable
                if (e instanceof KeeperException.NodeExistsException) {
                    logger.error(e);
                    e.printStackTrace();
                } else {
                    throw e;
                }
            }
            if (newLeader != null) {
                leading();
                //other things to process...
                //for example
              //MY 驻留
                System.out.println("1");
                synchronized(mutex){
                    try {
                        System.out.println("2");
                        mutex.wait();
                        System.out.println("3");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //完成任务后放弃leader权限,但继续竟选leader
                
                //模拟死亡
                System.out.println("4");
                System.exit(1);        //EXIT
                System.out.println("5");
            } else {
                System.out.println("12");
                synchronized(mutex){
                    mutex.wait();
                }
                System.out.println("13");
                //MY
                findLeader();////继续竟争master
            }
        }
    }
 
    @Override
    public void process(WatchedEvent event) {
        System.out.println("9");
        if(event.getState() == KeeperState.SyncConnected){
            //MY
            //connectedSignal.countDown();
        }
         
        if (event.getPath().equals(root + "/leader") ) {
            if(event.getType() == Event.EventType.NodeCreated){
                System.out.println("得到通知-leader NodeCreated");
                //RAW
//                super.process(event);
//                following();
                
            }
            //MY 删除master时通知其它followers竟争选择新master
            if(event.getType() == Event.EventType.NodeDeleted){
                System.out.println("6");
                synchronized(mutex){
                    //System.out.println("7");
                    mutex.notify();    //如果每个应用中只存在一个waiter则可以使用这方法,否则使用notifyAll()
                } 
                System.out.println("8");
                //MY
                //模拟:如果是本server宕机了,删除master node(如果没删除),让其它nodes选举一个继任master
//                try {
//                    byte[] localhost = InetAddress.getLocalHost().getAddress();
//                    byte[] leader = zk.getData(root + "/leader", true, null);
//                    if(new String(localhost).equals(new String(leader))){
//                        zk.delete(root + "/leader", -1);
//                        //退出本应用.所以本应用最好使用TestMainServer先运行提供服务,
//                        //而不是利用一个启动LeaderElection驻留来提供服务
//                    }else{
//                        //do nothing,其它node继续寻求继任master
//                    }
//                } catch (UnknownHostException e) {
//                    e.printStackTrace();
//                } catch (KeeperException e) {
//                    e.printStackTrace();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            }
        }
    }
 
    void leading() {
        System.out.println("成为领导者");
    }
 
    void following() {
        System.out.println("成为组成员");
    }
 
    public static void main(String[] args) {
//        TestMainServer.start();        //if enable this clause,the flag EXIT must be commented
        String connectString = "localhost:" + TestMainServer.CLIENT_PORT;
 
        LeaderElection le = new LeaderElection(connectString, "/GroupMembers");
        try {
            le.findLeader();
        } catch (Exception e) {
            logger.error(e);
            e.printStackTrace();
        }
    }
}
  tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
Zookeeper 还支持另外一种伪集群的方式,也就是可以在一台物理机上运行多个 Zookeeper 实例(hbase也

集群模式配置(比单机模式多添加的项)
 initLimit=5
 syncLimit=2
 server.1=192.168.211.1:2888:3888
 server.2=192.168.211.2:2888:3888
* initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
* syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
* server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。

利用zkCli.sh -server <host>:<port>可以连接指定的zk Servers;
不同的host或port建立的nodes,是存放不同的.

zk.setData()方法后,watch恢复false默认
是否产生event只决定于最后一次的设置true/false

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-366198-1-1.html 上篇帖子: zookeeper-server-client 简单例子 下篇帖子: 关于zookeeper的讨论
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表