zookeeper分布式原理实战解析

来源:互联网 发布:远程数据采集器 编辑:程序博客网 时间:2024/06/05 06:56

1.本实验基于centos7.3 +虚拟机VM+zookeeper-3.4.5.tar.gz环境下安装了三台集群测试。
安装参考:http://www.linuxidc.com/Linux/2016-09/135052.htm
启动zookeeper集群shell脚本

 #!/bin/bashcd /opt/apps/zookeeper/bin ./zkServer.sh start ssh -tt root@192.168.32.131 > /dev/null 2>&1 << remotesshcd /opt/apps/zookeeper/bin./zkServer.sh startexit remotessh ssh -tt root@192.168.32.130 > /dev/null 2>&1 << remotesshcd /opt/apps/zookeeper/bin ./zkServer.sh start exit remotessh

停止脚本:

 #!/bin/bash cd /opt/apps/zookeeper/bin ./zkServer.sh stop ssh -tt root@192.168.32.130 > /dev/null 2>&1 << remotessh cd /opt/apps/zookeeper/bin ./zkServer.sh stop exit remotessh ssh -tt root@192.168.32.131 > /dev/null 2>&1 << remotessh cd /opt/apps/zookeeper/bin ./zkServer.sh stop exit remotessh

2.zookeeper的服务上下线监听:
结构流程图:
这里写图片描述
实验测试:
服务端代码:

package com.ljt.zk.zkdist;import java.util.concurrent.CountDownLatch;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.ZooKeeper.States;/** *  * <p>Title: DistributedServer</p> * <p> 功能描述:: </p> * <p>Company: adteach </p>  * @author  刘建涛 *  * @date    2017年7月7日上午11:09:25 * @version 1.0 */public class DistributedServer {    // private static final String connectString =    // "192.168.32.129:2181,192.168.32.130:2182,192.168.32.131:2183";    private static final String connectString = "192.168.32.129:2181";    private static final int sessionTimeout = 15000;    private static final String parentNode = "/servers";    private ZooKeeper zk = null;    /**     * 创建到zk的客户端连接     *      * @throws Exception     */    public void getConnect(String agr) throws Exception {        //连接不成功等待连接        while (true) {            zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {                @Override                public void process(WatchedEvent event) {                    try {                        zk.getChildren("/servers", true);                        // 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)                        System.out.println(event.getType() + "---" + event.getPath());                        // 利用zk连接注册服务器信息                          registerServer(agr);                        // 启动业务功能                         handleBussiness(agr);                    } catch (Exception e) {                    }                }            });            if(States.CONNECTED != zk.getState()){                CountDownLatch connectedLatch = new CountDownLatch(1);                System.err.println("等待连接……");                connectedLatch.await();            }else{                System.err.println("连接成功!!!");                break;            }        }    }    /**     * 向zk集群注册服务器信息     *      * @param hostname     * @throws Exception     */    public void registerServer(String hostname) throws Exception {        String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE,                CreateMode.EPHEMERAL_SEQUENTIAL);        System.out.println(hostname + "is online.." + create);    }    /**     * 业务功能     *      * @throws InterruptedException     */    public void handleBussiness(String hostname) throws InterruptedException {        System.out.println(hostname + "start working.....");        Thread.sleep(Long.MAX_VALUE);    }    public static void main(String[] args) throws Exception {        // 获取zk连接        DistributedServer server = new DistributedServer();        server.getConnect(args[0]);    }}

启动时向main函数中注入参数结果如下:
打成jar包运行命令:java -jar jar包 参数
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper).
log4j:WARN Please initialize the log4j system properly.
等待连接……
None—null
www.ljt.cos01is online../servers/server0000000002
www.ljt.cos01start working…..

客服端代码:

package com.ljt.zk.zkdist;import java.util.ArrayList;import java.util.List;import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.KeeperException;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.ZooKeeper.States;/*** *  * <p>Title: DistributedClient</p> * <p> 功能描述:: </p> * <p>Company: adteach </p>  * @author  刘建涛 *  * @date    2017年7月7日上午11:12:48 * @version 1.0 */public class DistributedClient {    private static final String connectString = "192.168.32.129:2181,192.168.32.130:2182,192.168.32.131:2183";    private static final int sessionTimeout = 8000;    private static final String parentNode = "/servers";    // 注意:加volatile的意义何在?    private volatile List<String> serverList;    private ZooKeeper zk = null;    /**     * 创建到zk的客户端连接     *      * @throws Exception     */    public void getConnect() throws Exception {        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {            @Override            public void process(WatchedEvent event) {                // 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)                try {                    // 重新更新服务器列表,并且注册了监听                    getServerList();                } catch (Exception e) {                }            }        });        CountDownLatch connectedLatch = new CountDownLatch(1);        if (States.CONNECTING == zk.getState()) {            try {                connectedLatch.await();            } catch (InterruptedException e) {                throw new IllegalStateException(e);            }        }    }    /**     * 获取服务器信息列表     *      * @throws Exception     */    public void getServerList() throws Exception {        // 获取服务器子节点信息,并且对父节点进行监听        List<String> children = zk.getChildren(parentNode, true);        // 先创建一个局部的list来存服务器信息        List<String> servers = new ArrayList<String>();        for (String child : children) {            // child只是子节点的节点名            byte[] data = zk.getData(parentNode + "/" + child, false, null);            servers.add(new String(data));        }        // 把servers赋值给成员变量serverList,已提供给各业务线程使用        serverList = servers;        // 打印服务器列表        System.out.println(serverList);    }    /**     * 业务功能     *      * @throws InterruptedException     */    public void handleBussiness() throws InterruptedException {        System.out.println("client start working.....");        Thread.sleep(Long.MAX_VALUE);    }    public static void main(String[] args) throws Exception {        // 获取zk连接        DistributedClient client = new DistributedClient();        client.getConnect();        // 获取servers的子节点信息(并监听),从中获取服务器信息列表        client.getServerList();        // 业务线程启动        client.handleBussiness();    }}

3.分布式共享锁
分布式锁结构流程图:
这里写图片描述
这里写图片描述

完整代码:

package com.ljt.zk.zklock;import java.util.Collections;import java.util.List;import java.util.Random;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooKeeper;public class DistributedClientLock {    // 会话超时    private static final int SESSION_TIMEOUT = 2000;    // zookeeper集群地址    private String hosts =              "192.168.32.129:2181,192.168.32.130:2182,192.168.32.131:2183";    private String groupNode = "locks";    private String subNode = "sub";    private boolean haveLock = false;    private ZooKeeper zk;    // 记录自己创建的子节点路径    private volatile String thisPath;    /**     * 连接zookeeper     */    public void connectZookeeper() throws Exception {        zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() {            public void process(WatchedEvent event) {                try {                    // 判断事件类型,此处只处理子节点变化事件                    if (event.getType() == EventType.NodeChildrenChanged && event.getPath().equals("/" + groupNode)) {                        //获取子节点,并对父节点进行监听                        List<String> childrenNodes = zk.getChildren("/" + groupNode, true);                        String thisNode = thisPath.substring(("/" + groupNode + "/").length());                        // 去比较是否自己是最小id                        Collections.sort(childrenNodes);                        if (childrenNodes.indexOf(thisNode) == 0) {                            //访问共享资源处理业务,并且在处理完成之后删除锁                            doSomething();                            //重新注册一把新的锁                            thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,                                    CreateMode.EPHEMERAL_SEQUENTIAL);                        }                    }                } catch (Exception e) {                    e.printStackTrace();                }            }        });        // 1、程序一进来就先注册一把锁到zk上        thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,                CreateMode.EPHEMERAL_SEQUENTIAL);        // wait一小会,便于观察        Thread.sleep(new Random().nextInt(1000));        // 从zk的锁父目录下,获取所有子节点,并且注册对父节点的监听        List<String> childrenNodes = zk.getChildren("/" + groupNode, true);        //如果争抢资源的程序就只有自己,则可以直接去访问共享资源         if (childrenNodes.size() == 1) {            doSomething();            thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,                    CreateMode.EPHEMERAL_SEQUENTIAL);        }    }    /**     * 处理业务逻辑,并且在最后释放锁     */    private void doSomething() throws Exception {        try {            System.out.println("gain lock: " + thisPath);            Thread.sleep(2000);            // do something        } finally {            System.out.println("finished: " + thisPath);            //  删除节点            zk.delete(this.thisPath, -1);        }    }    public static void main(String[] args) throws Exception {        DistributedClientLock dl = new DistributedClientLock();        dl.connectZookeeper();        Thread.sleep(Long.MAX_VALUE);    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 魅族手机玩王者荣耀卡怎么办 魅族手机导航gps信号弱怎么办 魅族手机4g信号差怎么办 魅族手机下面一排键失灵怎么办 魅族手机冲不进去电怎么办 苹果账号付款了又让付款怎么办 魅蓝3s开机定屏怎么办 魅族手机未找到固件怎么办不用电脑 魅族手机触屏局部失灵怎么办 更新了魅蓝的新系统掉帧怎么办 手机后盖摔了一下凹了一个洞怎么办 魅族手机充电需要重启怎么办 网上预约好了但就诊卡丢了怎么办 如果魅族手机锁屏密码忘记了怎么办 魅族手机应用加密忘记密码了怎么办 小米电视盒子3s死机黑屏怎么办 小米note充电充不进去电怎么办 乐视手机otg功能用不了怎么办 小米4c手机玩王者荣耀卡怎么办 捡的小米6被锁了怎么办 小米5s手机玩穿越火线卡怎么办 苹果平板更新完系统登录不上怎么办 谷歌商店一直卡在核对信息怎么办 贴吧邮箱忘了无法登陆怎么办 华为手机绑定了账号忘了怎么办 淘宝的手机多次注册无法登录怎么办 电脑看不到U盘里面的文件怎么办 c盘访问权限被锁了怎么办 xp系统电脑开机密码忘记了怎么办 华为荣耀9用久了卡怎么办 华为p9相机模糊敲打就正常怎么办 华为p9蓝频按什么都没反映怎么办 华为手机p9开机密码忘了怎么办 华为P9手机开机一直闪屏怎么办 荣耀畅玩7x用户数据锁定怎么办 华为手机p9的指纹解锁坏了怎么办 华为P9青春版外放音量小怎么办 华为麦芒5的开关键失灵怎么办 小米手机进水黑屏但是有声音怎么办 小米5手机突然黑屏没电怎么办 小米4开不了机怎么办充电没反应