4、Zookeeper实战

分布式安装部署

  1. 集群规划
    在hadoop-100,hadoop-101,hadoop-102三个节点上部署Zookeeper
  2. 解压Zookeeper
  3. 创建zkDate目录
  4. 在zkData目录下常见myid文件
  5. 修改zoo_sample.cfg文件为zoo.cfg文件
  6. 把hadoop-100上的/opt/module/zookeeper-3.4.10分发到hadoop-101和hadoop-102上
    [hadoop@hadoop-100 module]$ xsync zookeeper-3.4.10/
  7. 配置服务器编号
    在hadoop-100,hadoop-101,hadoop-102分别修改myid文件为1,2,3
  8. 配置zoo.cfg文件
    在hadoop-100上修改数据存储路径
    dataDir=/opt/module/zookeeper-3.4.10/zkData
    并增加如下配置
    server.1=hadoop-100:2888:3888
    server.2=hadoop-101:2888:3888
    server.3=hadoop-102:2888:3888
    配置参数解读
    server.A=B:C:D
    A是一个数字,表示这个是第几号服务器
    集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server
    B是这个服务器的ip地址
    C是这个服务器与集群中的Leader服务器交换信息的端口
    D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口
  9. 同步zoo.cfg文件
    [hadoop@hadoop-100 conf]$ xsync zoo.cfg
  10. 集群操作
    分别启动Zookeeper
    [hadoop@hadoop-100 zookeeper-3.4.10]$ bin/zkServer.sh start
    [hadoop@hadoop-101 zookeeper-3.4.10]$ bin/zkServer.sh start
    [hadoop@hadoop-102 zookeeper-3.4.10]$ bin/zkServer.sh start
    查看状态
    [hadoop@hadoop-100 zookeeper-3.4.10]$ bin/zkServer.sh status
    [hadoop@hadoop-101 zookeeper-3.4.10]$ bin/zkServer.sh status
    [hadoop@hadoop-102 zookeeper-3.4.10]$ bin/zkServer.sh status

客户端命令行操作

命令基本语法 功能描述
help 显示所有操作命令
ls path [watch] 使用 ls 命令来查看当前znode中所包含的内容
ls2 path [watch] 查看当前节点数据并能看到更新次数等数据
create 普通创建 -s 含有序列 -e 临时(重启或者超时消失)
get path [watch] 获得节点的值
set 设置节点的具体值
stat 查看节点状态
delete 删除节点
rmr 递归删除节点
  1. 启动客户端
    [hadoop@hadoop-100 zookeeper-3.4.10]$ bin/zkCli.sh
  2. 显示所有操作命令
    [zk: localhost:2181(CONNECTED) 0] help
  3. 查看当前znode中所包含的内容
    [zk: localhost:2181(CONNECTED) 1] ls /
  4. 查看当前节点详细数据
    [zk: localhost:2181(CONNECTED) 2] ls2 /
  5. 创建两个普通节点
    [zk: localhost:2181(CONNECTED) 3] create /test "hello Zookeeper"
    [zk: localhost:2181(CONNECTED) 4] create /test/hello "hello i use zookeeper"
  6. 获得节点的值
    [zk: localhost:2181(CONNECTED) 5] get /test
    [zk: localhost:2181(CONNECTED) 6] get /test/hello
  7. 创建短暂节点
    create -e /test/ephemeral "Ephemeral data"
    在当前客户端查看
    [zk: localhost:2181(CONNECTED) 8] ls /test
    退出当前客户端
    [zk: localhost:2181(CONNECTED) 9] quit
    重启客户端
    [hadoop@hadoop-100 zookeeper-3.4.10]$ bin/zkCli.sh
    再次查看,节点已经删除
    ls /test
  8. 创建带序号的节点
    先创建普通节点
    [zk: localhost:2181(CONNECTED) 3] create /test/sdata "sdata"
    创建再序号的节点
    [zk: localhost:2181(CONNECTED) 5] create -s /test/sdata/data "hello"
    [zk: localhost:2181(CONNECTED) 5] create -s /test/sdata/data "hello"
    [zk: localhost:2181(CONNECTED) 5] create -s /test/sdata/data "hello"
    如果原来没有序号节点,序号从0开始依次递增。如果原节点下已有2个节点,则再排序时从2开始,以此类推
  9. 修改节点数据值
    [zk: localhost:2181(CONNECTED) 10] set /test/hello "hhh"
  10. 节点的值变化监听
    在hadoop-101上注册监听/test/hello节点数据变化
    [zk: localhost:2181(CONNECTED) 0] get /test/hello watch
    在hadoop-100上修改/test/hello的数据
    [zk: localhost:2181(CONNECTED) 11] set /test/hello "hhhh"
    在hadoop-101上观察收到的数据变化的监听
    [zk: localhost:2181(CONNECTED) 1]
    WATCHER::
    WatchedEvent state:SyncConnected type:NodeDataChanged path:/test/hello
  11. 节点的子节点变化监听(路径变化)
    在hadoop-101上监听/test节点的子节点的变化
    [zk: localhost:2181(CONNECTED) 2] ls /test watch
    在hadoop-100/test节点上创建子节点
    [zk: localhost:2181(CONNECTED) 12] create -s /test/watch "hhh"
    在hadoop-101上观察收到子节点变化的监听
    [zk: localhost:2181(CONNECTED) 3]
    WATCHER::
    WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/test
  12. 删除节点
    [zk: localhost:2181(CONNECTED) 14] delete /test/watch0000000003
  13. 递归删除节点
    [zk: localhost:2181(CONNECTED) 15] rmr /test
  14. 查看节点状态
    stat /

API应用

环境准备

创建maven工程
添加pom文件

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>
</dependencies>

在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.File=target/spring.log  
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

创建Zookeeper客户端

private static String connectString = "hadoop-100:2181,hadoop-101:2181,hadoop-102:2181";
    private static int sessionTime = 2000;
    private ZooKeeper zkClient = null;

    @Test
    public void init() throws IOException {
        zkClient = new ZooKeeper(connectString, sessionTime, null);
    }

创建子节点

@Test
    public void create() throws KeeperException, InterruptedException {
        // 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
        String s = zkClient.create("/test", "testApi".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }

获取子节点并监听节点变化

@Before
    public void init() throws IOException {
        zkClient = new ZooKeeper(connectString, sessionTime, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("watchedEvent.getType() = " + watchedEvent.getType());
                System.out.println("watchedEvent.getPath() = " + watchedEvent.getPath());
                try {
                    zkClient.getChildren("/", true);
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
@Test
    public void getDataAndWatch() throws KeeperException, InterruptedException {
        List<String> children = zkClient.getChildren("/", true);
        for(String data : children) {
            System.out.println("data = " + data);
        }
        Thread.sleep(Long.MAX_VALUE);
    }

判断Znode是否存在

@Test
    public void exist() throws KeeperException, InterruptedException {
        Stat exists = zkClient.exists("/test/apii", false);
        System.out.println(exists == null ? "not exist" : "exist");
    }

监听服务器节点动态上下线案例

需求

某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线

需求分析

服务器动态上下线.png

具体实现

  1. 先在集群上创建/servers节点
    [zk: localhost:2181(CONNECTED) 10] create /servers "servers"
  2. 服务端代码
public class DistributeServer {

    private static String connectString = "hadoop-100:2181,hadoop-101:2181,hadoop-102:2181";
    private static int sessionTimeout = 2000;
    private ZooKeeper zk = null;
    private String parentNode = "/servers";
    
    // 创建到zk的客户端连接
    public void getConnect() throws IOException{
        
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

            @Override
            public void process(WatchedEvent event) {

            }
        });
    }
    
    // 注册服务器
    public void registServer(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);
    }
    
    // 业务功能
    public void business(String hostname) throws Exception{
        System.out.println(hostname+" is working ...");
        
        Thread.sleep(Long.MAX_VALUE);
    }
    
    public static void main(String[] args) throws Exception {
        
// 1获取zk连接
        DistributeServer server = new DistributeServer();
        server.getConnect();
        
        // 2 利用zk连接注册服务器信息
        server.registServer(args[0]);
        
        // 3 启动业务功能
        server.business(args[0]);
    }
}

  1. 客户端代码
public class DistributeClient {
    private static String connectString = "hadoop-100:2181,hadoop-101:2181,hadoop-102:2181";
    private static int sessionTimeout = 2000;
    private ZooKeeper zk = null;
    private String parentNode = "/servers";

    // 创建到zk的客户端连接
    public void getConnect() throws IOException {
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

            @Override
            public void process(WatchedEvent event) {

                // 再次启动监听
                try {
                    getServerList();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    // 获取服务器列表信息
    public void getServerList() throws Exception {
        
        // 1获取服务器子节点信息,并且对父节点进行监听
        List<String> children = zk.getChildren(parentNode, true);

        // 2存储服务器信息列表
        ArrayList<String> servers = new ArrayList<>();
        
        // 3遍历所有节点,获取节点中的主机名称信息
        for (String child : children) {
            byte[] data = zk.getData(parentNode + "/" + child, false, null);

            servers.add(new String(data));
        }

        // 4打印服务器列表信息
        System.out.println(servers);
    }

    // 业务功能
    public void business() throws Exception{

        System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
    }

    public static void main(String[] args) throws Exception {

        // 1获取zk连接
        DistributeClient client = new DistributeClient();
        client.getConnect();

        // 2获取servers的子节点信息,从中获取服务器信息列表
        client.getServerList();

        // 3业务进程启动
        client.business();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容