史上最完整的大数据学习(四) Zookeeper 完结篇 (API操作, shell命令 ,ZooKeeperACL 以及 分布式应用)

Zookeeper的认识以及节点详情

ZooKeeper的安装使用

六、Java API操作

6.1 原生 API

1)Maven依赖

 <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <type>pom</type>
        </dependency>

2)相关操作

(1)获得客户端对象
 private  ZooKeeper zooKeeper;

    @Before
    public void getCline() throws Exception{

         zooKeeper = new ZooKeeper("192.168.134.99:2181",2000,null);

    }
(2)获取节点值
 @Test
    public void getData()throws Exception{

        /*获取节点值*/
        byte[] data = zooKeeper.getData("/baizhi/123", null, null);
        System.out.println(new String(data));
    }

(3)获取节点孩子
  @Test
    public void getChild() throws Exception{

        /*获取当前输入节点下的子节点*/
        List<String> children = zooKeeper.getChildren("/baizhi/gjf", null);
        children.forEach((a)->{
            System.out.println(a);
        });

    }
(4)创建节点

    @Test
    public void createNode() throws Exception{


        /*创建持久节点*/

        Object value = null;

        value = "12312312";


        byte[] bytes = ((String) value).getBytes();


        String s = zooKeeper.create("/baizhi/123", bytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(s);




    }

(5)更新节点值
 @Test
    public void setData() throws Exception{

        Stat stat = zooKeeper.setData("/baizhi/123", new String("123123").getBytes(), -1);

        System.out.println(stat);


    }
(6)判断节点是否存在
 @Test
    public void exist() throws Exception{

        Stat stat = zooKeeper.exists("/baizhi/13", false);

        if (stat==null) {
            System.out.println("该节点不存在!");
        }else {
            System.out.println("该节点存在!");
        }

    }

6.2 zkCline API

1)Mavne依赖

<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.8</version>
</dependency>

2)核心API

 ZkClient client=new ZkClient("ip:port");                         

3)相关操作

package test;

import org.I0Itec.zkclient.ZkClient;

import java.util.List;

/**
 * Create by GuoJF on 2019/3/12
 */
public class Main {
    public static void main(String[] args) {


        ZkClient zkClient = new ZkClient("192.168.134.5:2181");


        /*
        * 获取根目录下所有的node信息
        *
        * */
        List<String> children = zkClient.getChildren("/");

        children.forEach((a)->{
            System.out.println(a);
        });

    }
}

(1)创建节点

    @Test
    public void createNode() {

        String result = zkClient.create("/baizhi/001", "001", CreateMode.PERSISTENT);

        System.out.println(result);

    }

(2)获取节点

 @Test
    public void getData() {
        Object readData = zkClient.readData("/baizhi/001");

        System.out.println(readData.toString());

    }

(3)更新节点值

 @Test
    public void setData() {
        zkClient.writeData("/baizhi/001", "123123");
    }

(4)删除节点

 @Test
    public void delNode() {

        boolean delete = zkClient.delete("/baizhi/001");
        if (delete) {
            System.out.println("删除成功!");
        } else {
            System.out.println("删除失败或者节点不存在!");
        }
    }

(5)判断节点是否存在

 @Test
    public void exist(){

        boolean exists = zkClient.exists("/baizhi/001");
        if (exists){
            System.out.println("该节点已经存在!");
        }else {
            System.out.println("该节点不存在!");
        }

    }

(6)获取孩子节点

 @Test
    public void getChild(){

        List<String> children = zkClient.getChildren("/baizhi");

        for (String child : children) {

            System.out.println(child);
        }
    }

6.3 Curator API

1)Maven依赖

 <dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-framework</artifactId>
   <version>2.7.1</version>
 </dependency>

2)相关操作

(1)获取客户端对象
  private CuratorFramework curatorFramework;

    @Before
    public void getClient() {

        /*
         * 重连策略 四种实现
         *  ExponentialBackoffRetry、RetryNTimes、RetryOneTimes、RetryUntilElapsed
         * */


        ExponentialBackoffRetry backoffRetry = new ExponentialBackoffRetry(1000, 1000);

        curatorFramework = CuratorFrameworkFactory.newClient("192.168.134.99:2181", backoffRetry);

        curatorFramework.start();


    }

(2)创建节点
  @Test
    public void createNode() throws Exception {
    String s = curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/baizhi/002", new String("123").getBytes());
        System.out.println(s);
    }
(3)获取节点
 @Test
    public void getData() throws Exception {

        byte[] bytes = curatorFramework.getData().forPath("/baizhi/002");

        System.out.println(new String(bytes));
    }
(4)更新节点值
@Test
    public void setData() {

        try {
            curatorFramework.setData().forPath("/baizhi/001", new String("123123").getBytes());

            System.out.println("更新成功!");
        } catch (KeeperException.NoNodeException e) {

            System.out.println("更新失败,该节点不存在!");
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
(5)获取孩子节点
 @Test
    public void getChild() throws Exception {
        curatorFramework.getChildren().forPath("/baizhi").forEach((child) -> {
            System.out.println(child);
        });
    }
(6)删除节点
    @Test
    public void delNode() throws Exception {
        curatorFramework.delete().forPath("/baizhi/002");
    }

6.4 Watcher接口

1)原生API实现Watch接口

在这里使用的是原生的Apache的Java API

<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
	<groupId>org.apache.zookeeper</groupId>
		<artifactId>zookeeper</artifactId>
	<version>3.4.6</version>
	<type>pom</type>
</dependency>

ZooKeeper Watcher监视使客户端能够接收来自ZooKeeper服务器的通知,并在发生时处理这些事件。 ZooKeeper Java API提供了一个名为Watcher的公共接口,客户端事件处理程序类必须实现该接口才能接收有关来自ZooKeeper服务器的事件通知。 以编程方式,使用这种客户端的应用程序通过向客户端注册回调(callback)对象来处理这些事件。

package test;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;
import java.util.UUID;

/**
 * Create by GuoJF on 2019/3/12
 */
public class DataUpdater  {

    private static String hostPort = "192.168.134.5:2181";
    private static String zooDataPath = "/baizhi/gjf";
    ZooKeeper zk;

    public DataUpdater() throws IOException {
        try {
            zk = new ZooKeeper(hostPort, 2000, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() throws InterruptedException, KeeperException {
        while (true) {
            String uuid = UUID.randomUUID().toString();
            byte zoo_data[] = uuid.getBytes();
            zk.setData(zooDataPath, zoo_data, -1);
            try {
                Thread.sleep(5000); // Sleep for 5 secs
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        DataUpdater dataUpdater = new DataUpdater();
        dataUpdater.run();
    }
}
package test;


import org.apache.zookeeper.*;

/**
 * Create by GuoJF on 2019/3/13
 */
public class DataWatcher implements Watcher,Runnable {


    ZooKeeper zooKeeper;

    public DataWatcher() {

        try {
              zooKeeper = new ZooKeeper("192.168.134.5:2181",2000,this);

              if (zooKeeper.exists("/baizhi/gjf",this)==null) {

                  zooKeeper.create("/baizhi/gjf", "get".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

              }

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {

        DataWatcher dataWatcher = new DataWatcher();

        dataWatcher.run();

    }


    @Override
    public void process(WatchedEvent event) {

        if (event.getType() == Event.EventType.NodeDataChanged){
            System.out.println("数据发改变了吧");

            try {
                byte[] data = zooKeeper.getData("/baizhi/gjf", this, null);

                String s = new String(data);

                System.out.println(s);

            }catch (Exception e){

            }

        }

    }

    public void run() {
        try {
            synchronized (this) {
                while (true) {
                    wait();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }
}

2)ZkClient实现Watcher接口

@Test
    public void watcherInterface() throws Exception {
        zkClient.subscribeDataChanges("/baizhi/gjf", new IZkDataListener() {
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {
                System.out.println("节点名称:" + dataPath);
                System.out.println("节点名称:" + data.toString());

            }

            @Override
            public void handleDataDeleted(String dataPath) throws Exception {

            }
        });


        Thread.sleep(Integer.MAX_VALUE);
    }

3)Curator API实现Watcher接口

ZooKeeper原生的API支持通过注册Watcher来进行事件监听,但是Watcher通知是一次性的,因此开发过程中需要反复注册Watcher,比较繁琐。Curator引入了Cache来监听ZooKeeper服务端的事件。Cache对ZooKeeper事件监听进行了封装,能够自动处理反复注册监听,简化了ZooKeeper原生API繁琐的开发过程。

   		 <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.7.1</version>
        </dependency>
(1)NodeCache

​ 监听指定的数据变化


        /*
         *NodeCache
         *
         * */

        //在注册监听器的时候,如果传入此参数,当事件触发时,逻辑由线程池处理
        ExecutorService pool = Executors.newFixedThreadPool(2);

        NodeCache nodeCache = new NodeCache(curatorFramework, "/baizhi/gjf", false);

        nodeCache.start(true);

        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                System.out.println(new String(nodeCache.getCurrentData().getData()));
            }
        }, pool);

(2)PathChildrenCache

​ 监听指定节点下所有子节点的数据变化


        /**
         * 监听子节点的变化情况
         */
        PathChildrenCache childrenCache = new PathChildrenCache(curatorFramework, "/baizhi", true);
        childrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
        childrenCache.getListenable().addListener(
                new PathChildrenCacheListener() {
                    @Override
                    public void childEvent(CuratorFramework client, PathChildrenCacheEvent event)
                            throws Exception {
                        switch (event.getType()) {
                            case CHILD_ADDED:
                                System.out.println("CHILD_ADDED: " + event.getData().getPath());
                                break;
                            case CHILD_REMOVED:
                                System.out.println("CHILD_REMOVED: " + event.getData().getPath());
                                break;
                            case CHILD_UPDATED:
                                System.out.println("CHILD_UPDATED: " + event.getData().getPath());
                                break;
                            default:
                                break;
                        }
                    }
                },
                pool
        );

七、Zookeeper ACL

7.1 Shell 操作

zookeeper本身提供了ACL机制,表示为scheme: id:permissions,第一个字段表示采用哪一种机制,第二个id表示用户,permissions表示相关权限(如只读,读写,管理等)。

7.1 .1 scheme :id 介绍

  • world: 它下面只有一个id, 叫anyone, world:anyone代表任何人,zookeeper中对所有人有权限的结点就是属于world:anyone的
  • auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持通过kerberos来进行authencation, 也支持username/password形式的authentication),使用auth来设置权限的时候,需要在zk里注册一个用户才可以
  • digest: 它对应的id为username:BASE64(SHA1(password)),它需要先通过username:password形式的authentication
  • ip: 它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如ip:192.168.1.0/16, 表示匹配前16个bit的IP段
  • super: 在这种scheme情况下,对应的id拥有超级权限,可以做任何事情(cdrwa)

7.1 .2 permissions

权限ACL简写描述
CREATEc可以创建子节点
DELETEd可以删除子节点(仅下一级节点)
READr可以读取节点数据及显示子节点列表
WRITEw可以设置节点数据
ADMINa可以设置节点访问控制列表权限

7.1.3 ACL Shell 命令

命令使用方式描述
getAclgetAcl 读取ACL权限
setAclsetAcl 设置ACL权限
addauthaddauth 添加认证用户

7.1.4 操作

World scheme

其实默认就是Word Scheme

语法
setAcl <path> world:anyone:<acl>
#随便创建一个节点
[zk: localhost:2181(CONNECTED) 61] create /baizhiedu 1
Created /baizhiedu
[zk: localhost:2181(CONNECTED) 62] getAcl /baizhiedu
'world,'anyone
: cdrwa

在这里插入图片描述

#在创建完成后相关节点,还可以通过setAcl的方式设置相关权限
[zk: localhost:2181(CONNECTED) 64] setAcl的方式设置相关权限 /baizhiedu  world:anyone:cdrw
cZxid = 0x1c631
ctime = Tue Jul 09 08:37:06 CST 2019
mZxid = 0x1c631
mtime = Tue Jul 09 08:37:06 CST 2019
pZxid = 0x1c631
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0
[zk: localhost:2181(CONNECTED) 67] getAcl /baizhiedu
'world,'anyone
: cdrw
IP scheme

对于特定IP适用,其他没有设置过的IP没有相关权限

语法
setAcl <path> ip:<ip>:<acl>
[zk: localhost:2181(CONNECTED) 73] setAcl /baizhi01 ip:192.168.123.111:cdrwa
cZxid = 0x1c635
ctime = Tue Jul 09 08:44:14 CST 2019
mZxid = 0x1c635
mtime = Tue Jul 09 08:44:14 CST 2019
pZxid = 0x1c635
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0


[zk: localhost:2181(CONNECTED) 78] getAcl /baizhi01
'ip,'192.168.123.111
: cdrwa

[zk: localhost:2181(CONNECTED) 79] get /baizhi01
Authentication is not valid : /baizhi01
Auth scheme
语法
addauth digest <user>:<password> #添加认证用户
setAcl <path> auth:<user>:<acl>
[zk: localhost:2181(CONNECTED) 81] addauth digest gjf:root
[zk: localhost:2181(CONNECTED) 82] setAcl /baizhi03  auth:gjf:root
cZxid = 0x1c637
ctime = Tue Jul 09 08:47:00 CST 2019
mZxid = 0x1c637
mtime = Tue Jul 09 08:47:00 CST 2019
pZxid = 0x1c637
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0

[zk: localhost:2181(CONNECTED) 95] getAcl /baizhi03
'digest,'gjf:bbYGkKPfBgiZDzcwrmVylqDlXnI=
: cdrwa
Digest scheme
语法
setAcl <path> digest:<user>:<password>:<acl>
计算密文
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64

[root@GuoJiafeng01 ~]# echo -n gjf:root | openssl dgst -binary -sha1 | openssl base64
bbYGkKPfBgiZDzcwrmVylqDlXnI=

[zk: localhost:2181(CONNECTED) 98] create /baizhi04 1
Created /baizhi04
[zk: localhost:2181(CONNECTED) 99] setAcl /baizhi04 digest:gjf:bbYGkKPfBgiZDzcwrmVylqDlXnI=:a
cZxid = 0x1c641
ctime = Tue Jul 09 08:59:18 CST 2019
mZxid = 0x1c641
mtime = Tue Jul 09 08:59:18 CST 2019
pZxid = 0x1c641
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0
[zk: localhost:2181(CONNECTED) 100] getAcl /baizhi04
'digest,'gjf:bbYGkKPfBgiZDzcwrmVylqDlXnI=
: a

# 当前是没有权限的
[zk: localhost:2181(CONNECTED) 101] get /baizhi04
Authentication is not valid : /baizhi04

# 在当前session中添加认证用户
[zk: localhost:2181(CONNECTED) 102] addauth digest gjf:root
#就能获取到相关的权限了
[zk: localhost:2181(CONNECTED) 107] get /baizhi04
1
cZxid = 0x1c641
ctime = Tue Jul 09 08:59:18 CST 2019
mZxid = 0x1c641
mtime = Tue Jul 09 08:59:18 CST 2019
pZxid = 0x1c641
cversion = 0
dataVersion = 0
aclVersion = 2
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0



7.2 Java API

 @Before
    public void getClient() {

        /*
         * 重连策略 四种实现
         *  ExponentialBackoffRetry、RetryNTimes、RetryOneTimes、RetryUntilElapsed
         * */

        ACLProvider aclProvider = new ACLProvider() {
            private List<ACL> acl ;
            @Override
            public List<ACL> getDefaultAcl() {
                if(acl ==null){
                    ArrayList<ACL> acl = ZooDefs.Ids.CREATOR_ALL_ACL;
                    acl.clear();
                    acl.add(new ACL(ZooDefs.Perms.ALL, new Id("digest", "admin:123") ));
                    this.acl = acl;
                }
                return acl;
            }

            @Override
            public List<ACL> getAclForPath(String path) {
                return null;
            }
        };

        ExponentialBackoffRetry backoffRetry = new ExponentialBackoffRetry(1000, 1000);

        //curatorFramework = CuratorFrameworkFactory.builder().aclProvider(aclProvider).authorization("digest", "admin:123".getBytes()).connectString("192.168.134.99:2181").retryPolicy(backoffRetry).build();
         curatorFramework = CuratorFrameworkFactory.newClient("192.168.134.99:2181", backoffRetry);

        this.curatorFramework.start();


    }

八、应用

8.1 分布式高可用(简单)

package test.ha;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Create by rechen on 2020/7/10
 */
public class App {

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

        Integer port = 1233;
        ExponentialBackoffRetry backoffRetry = new ExponentialBackoffRetry(1000, 1000);

        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("192.168.134.99:2181", backoffRetry);

        curatorFramework.start();

        Stat stat = curatorFramework.checkExists().forPath("/baizhi/test01");
        if (stat == null) {

            curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath("/baizhi/test01", new String("localhost:" + port).getBytes());
            soutFunction(port);
        } else {

            System.out.println("当前节点已经存在,主机服务为:" + new String(curatorFramework.getData().forPath("/baizhi/test01")));

            System.out.println("当前主机自动切换为StandyBy状态");

        }



        /*
         *NodeCache
         *
         * */

        //在注册监听器的时候,如果传入此参数,当事件触发时,逻辑由线程池处理
        ExecutorService pool = Executors.newFixedThreadPool(2);


        /**
         * 监听子节点的变化情况
         */
        PathChildrenCache childrenCache = new PathChildrenCache(curatorFramework, "/baizhi", true);
        childrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
        childrenCache.getListenable().addListener(
                new PathChildrenCacheListener() {
                    @Override
                    public void childEvent(CuratorFramework client, PathChildrenCacheEvent event)
                            throws Exception {
                        switch (event.getType()) {
                            case CHILD_ADDED:
                                System.out.println("节点上线: " + event.getData().getPath());
                                break;
                            case CHILD_REMOVED:
                                System.out.println("节点下线: " + event.getData().getPath());
                                System.out.println("正在上线其他节点,请稍后。");
                                if (event.getData().getPath().endsWith("/baizhi/test01")) {
                                    try {
                                        curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath("/baizhi/test01", new String("localhost:" + port).getBytes());

                                        System.out.println("当前节点上线成功");
                                        soutFunction(port);
                                    } catch (Exception e) {

                                        if (e instanceof KeeperException.NodeExistsException) {
                                            System.out.println("当前节点上线失败,已有其他节点上线");

                                        }

                                    }
                                }
                                break;
                            case CHILD_UPDATED:
                                System.out.println("节点更新: " + event.getData().getPath());
                                break;
                            default:
                                break;
                        }
                    }
                },
                pool
        );


        Thread.sleep(Integer.MAX_VALUE);
    }


    public static void soutFunction(Integer port) {


        while (true) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("localhost:" + port + ",正在提供服务");
        }

    }

}

8.2 分布式高可用(优雅)

package test.ha;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.GetChildrenBuilder;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Create by rechen on 2020/7/10
 */
public class AppPro {


    public static void main(String[] args) throws Exception {
        final String[] lockip = {null};

        final Integer[] port = {1233, 1234, 1235, 1236};


        ExponentialBackoffRetry backoffRetry = new ExponentialBackoffRetry(1000, 1000);

        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("192.168.123.129:2181", backoffRetry);

        curatorFramework.start();


        List<String> stringList = curatorFramework.getChildren().forPath("/ha");

        System.out.println(stringList.size());


        if (stringList.size() == 0) {

            curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/ha/test01" + port[0], new String("localhost:" + port[0]).getBytes());
            soutFunction(port[0]);
        } else {

            System.out.println("当前节点已经存在,主机服务为:" + lockip);

            System.out.println("当前主机自动切换为StandyBy状态");

        }



        /*
         *NodeCache
         *
         * */

        //在注册监听器的时候,如果传入此参数,当事件触发时,逻辑由线程池处理
        ExecutorService pool = Executors.newFixedThreadPool(2);


        /**
         * 监听子节点的变化情况
         */
        PathChildrenCache childrenCache = new PathChildrenCache(curatorFramework, "/ha", true);
        childrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
        final String[] currentPath = {""};

        List<String> childers = curatorFramework.getChildren().forPath("/ha");

        Collections.sort(childers);

        currentPath[0] = childers.get(0);

        childrenCache.getListenable().addListener(
                new PathChildrenCacheListener() {
                    @Override
                    public void childEvent(CuratorFramework client, PathChildrenCacheEvent event)
                            throws Exception {
                        switch (event.getType()) {
                            case CHILD_ADDED:
                                //System.out.println("节点上线: " + event.getData().getPath());
                                break;
                            case CHILD_REMOVED:
                                if (event.getData().getPath().endsWith(currentPath[0])) {
                                    System.out.println("节点下线: " + event.getData().getPath());
                                    System.out.println("正在上线其他节点,请稍后。");
                                    String path = curatorFramework.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/ha/test01", new String("localhost:" + port[0]).getBytes());

                                    List<String> childers = curatorFramework.getChildren().forPath("/ha");


                                    Collections.sort(childers);

                                    currentPath[0] = childers.get(0);
                                    if (path.endsWith(childers.get(0))) {

                                        System.out.println("当前节点上线成功");
                                        soutFunction(port[0]);


                                    } else {
                                        System.out.println("当前节点上线失败!");
                                        System.out.println("删除当前节点!");
                                        try {
                                            curatorFramework.delete().forPath((path));
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }

                                        System.out.println((path) + "节点已经删除!");
                                    }

                                }
                                break;
                            case CHILD_UPDATED:
                                System.out.println("节点更新: " + event.getData().getPath());
                                break;
                            default:
                                break;
                        }
                    }
                },
                pool
        );

        Thread.sleep(Integer.MAX_VALUE);
    }


    public static void soutFunction(Integer port) {


        while (true) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("localhost:" + port + ",正在提供服务");
        }

    }

}

九、集群搭建

9.1 集群配置

1)添加添加配置文件

tickTime=2000
dataDir=/home/zk/data
clientPort=2181
initLimit=5
syncLimit=2
server.1=guojiafeng01:2887:3887
server.2=guojiafeng01:2888:3888
server.3=guojiafeng01:2889:3889

server.id=host:port:port

指出了不同的zk的服务器的自身的标示,作为集群中一部分及其应该知道集群中其他的机器,在datadir目录中创建一个文件名为myid的文件,这个文件仅仅含有一行内容,制定的是自身的id值。比如服务器的id是1就在这个文件写1,第一个port是保持和主机通信,第二个port是做选举的。

2)新建myid文件

在上述配置文件中对的data目录下,创建一个myid文件,在节点1中的myid中写 1 (就一个数字1),在节点2中写数字2,依次列推

3)复制配置启动

9.2 配置文件详解

1)ZK的最小配置

最小配置是指Zookeeper运行所需的最小配置,Zookeeper只需要配置这些项就可以正常的运行Zookeeper。

clientPort

配置ZK监听客户端连接的端口

dataDir

内存数据库快照存放地址,如果没有指定事务日志存放地址(dataLogDir),默认也是存放在这个路径下,建议两个地址分开存放到不同的设备上。

tickTime

心跳基本时间单位,毫秒级

2)ZK的高级配置(可选)

高级配置是指有的需要直接通过系统属性进行设置)

dataLogDir

将事务日志存储在该路径下,比较重要,这个日志存储的设备效率会影响ZK的写吞吐量。

globalOutstandingLimit

(Java system property: zookeeper.globalOutstandingLimit)默认值是1000,限定了所有连接到服务器上但是还没有返回响应的请求个数(所有客户端请求的总数,不是连接总数),这个参数是针对单台服务器而言,设定太大可能会导致内存溢出。

preAllocSize

(Java system property: zookeeper.preAllocSize)默认值64M,以KB为单位,预先分配额定空间用于后续transactionlog 写入,每当剩余空间小于4K时,就会又分配64M,如此循环。如果SNAP做得比较频繁(snapCount比较小的时候),那么请减少这个值。

snapCount

(Java system property: zookeeper.snapCount)默认值100,000,当transaction每达到snapCount/2+rand.nextInt(snapCount/2)时,就做一次SNAPSHOT,默认情况下是50,000~100,000条transactionlog就会做一次,之所以用随机数是为了避免所有服务器可能在同一时间做snapshot.

traceFile (Java system property: requestTraceFile)

maxClientCnxns

默认值是10,一个客户端能够连接到同一个服务器上的最大连接数,根据IP来区分。如果设置为0,表示没有任何限制。设置该值一方面是为了防止DoS攻击。

clientPortAddress

与clientPort匹配,表示某个IP地址,如果服务器有多个网络接口(多个IP地址),如果没有设置这个属性,则clientPort会绑定到所有IP地址上,否则只绑定到该设置的IP地址上。

minSessionTimeout

最小的session time时间,默认值是2个tick time,客户端设置的session time 如果小于这个值,则会被强制协调为这个最小值。

maxSessionTimeout

最大的session time 时间,默认值是20个tick time. ,客户端设置的session time 如果大于这个值,则会被强制协调为这个最大值。

3)ZK的集群配置选项

electionAlg

领导选举算法,默认是3(fast leader election,基于TCP),0表示leader选举算法(基于UDP),1表示非授权快速选举算法(基于UDP),2表示授权快速选举算法(基于UDP),目前1和2算法都没有应用,不建议使用,0算法未来也可能会被干掉,只保留3(fast leader election)算法,因此最好直接使用默认就好。

initLimit

tickTime的个数,表示在leader选举结束后,followers与leader同步需要的时间,如果followers比较多或者说leader的数据非常多时,同步时间相应可能会增加,那么这个值也需要相应增加。当然,这个值也是follower和observer在开始同步leader的数据时的最大等待时间(setSoTimeout)

syncLimit

tickTime的个数,这时间容易和上面的时间混淆,它也表示follower和observer与leader交互时的最大等待时间,只不过是在与leader同步完毕之后,进入正常请求转发或ping等消息交互时的超时时间。

leaderServes

(Java system property: zookeeper.leaderServes) 如果该值不是no,则表示该服务器作为leader时是需要接受客户端连接的。为了获得更高吞吐量,当服务器数三台以上时一般建议设置为no。

cnxTimeout

(Java system property: zookeeper.cnxTimeout) 默认值是5000,单位ms 表示leaderelection时打开连接的超时时间,只用在算法3中。

4)ZK安全配置

skipACL

(Java systemproperty: zookeeper.skipACL) 默认值是no,忽略所有ACL检查,相当于开放了所有数据权限给任何人。

forceSync

(Java systemproperty: zookeeper.forceSync) 默认值是yes, 表示transactionlog在commit时是否立即写到磁盘上,如果关闭这个选项可能会在断电时丢失信息。

jute.maxbuffer

(Java system property: jute.maxbuffer)默认值0xfffff,单位是KB,表示节点数据最多1M。如果要设置这个值,必须要在所有服务器上都需要设置。

授权认证配置项

DigestAuthenticationProvider.superDigest

(Java system property only: zookeeper.DigestAuthenticationProvider.superDigest) 设置这个值是为了确定一个超级用户,它的值格式为

super:<base64encoded(SHA1(idpassword))> ,一旦当前连接addAuthInfo超级用户验证通过,后续所有操作都不会checkACL.

到这里zookeeper就更新完成了

创作不易,希望大家给个三连吧~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值