springboot整合zookeeper3.4+Curator

zookeeper与Curator存在兼容性问题,官网描述https://curator.apache.org/zk-compatibility-34.html

 使用官网方案,自测不行,所以回退到使用Curator 2.x。zookeeper 3.4.x服务器版本与Curator 2.x是兼容的。

一、项目总pom.xml声明版本号

    <dependencyManagement>
        <dependencies>
            <!-- zookeeper -->
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>2.13.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.4.14</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

二、项目子模块pom.xml中引入依赖

    <dependencies>
        <!-- zookeeper -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
        </dependency>
    </dependencies>

三、zookeeper配置类

/**
 * zookeeper配置类
 *
 * @author
 * @date 2021/4/1
 */
@Slf4j
@Configuration
public class ZookeeperConfig {

    // @Value("${zookeeper.server}")
    private String zkAddress = "127.0.0.1:2181";

    @Autowired
    DemoService demoService;

    /**
     * 创建zk客户端,注入spring容器
     *
     * @return zk客户端
     */
    @Bean
    public CuratorFramework curatorFramework() {
        RetryForever retryForever = new RetryForever(10000);
        CuratorFramework client = CuratorFrameworkFactory.builder().connectString(zkAddress).retryPolicy(retryForever).build();
        client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {
                if (ConnectionState.RECONNECTED.equals(newState)) {
                    //重连成功,拉取最新数据同步
                    log.warn("zk重连成功,同步最新数据。");
                    client.sync();
                }
            }
        });
        client.getCuratorListenable().addListener(new CuratorListener() {
            @Override
            public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {
                log.info("zk接收到事件, CuratorEvent={}", event);
            }
        });
        //开启连接
        client.start();
        log.info("zookeeper 初始化完成...");

        //给节点注册监听,可监听到当前节点的多次增删改
        NodeCache nodeCache = new NodeCache(client, "zkPath", false);
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                log.info("NodeCache.nodeChanged(),path={}, data={}", nodeCache.getCurrentData().getPath(), new String(nodeCache.getCurrentData().getData()));
                //todo 业务处理。。。
                //demoService.doWork();
            }
        });
        try {
            nodeCache.start(true);
        } catch (Exception e) {
            log.error("nodeCache start fail, {}", e);
            throw new RuntimeException("nodeCache start fail", e);
        }

        //监听父节点下的所有子节点(可监听多次)
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/parentPath", true);
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                if (event.getData() == null) {
                    return;
                }
                log.info("ZK PathChildrenCache监听到子节点事件,path={}, data={}", event.getData().getPath(), new String(event.getData().getData()));               
                //todo 业务处理。。。
                //demoService.doWork2();
            }
        });
        try {
            pathChildrenCache.start();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return client;
    }

}

四、zookeeper的服务提供类

/**
 * Zookeeper服务接口
 *
 * @author yangzihe
 * @date 2021/4/2
 */
public interface ZookeeperService {

    /**
     * 判断节点是否存在
     */
    boolean isExistNode(String path);

    /**
     * 创建节点
     */
    void createNode(CreateMode mode, String path);

    /**
     * 设置节点数据
     */
    void setNodeData(String path, String nodeData);

    /**
     * 创建/更新节点及其节点数据
     */
    void updateNodeAndData(String path, String nodeData);

    /**
     * 获取节点数据
     */
    String getNodeData(String path);

    /**
     * 获取节点下数据
     */
    List<String> getNodeChild(String path);

    /**
     * 是否递归删除节点
     */
    void deleteNode(String path, Boolean recursive);

    
}

实现类:

/**
 * Zookeeper服务接口实现
 *
 * @author yangzihe
 * @date 2021/4/2
 */
@Slf4j
@Service
public class ZookeeperServiceImpl implements ZookeeperService {

    @Autowired
    private CuratorFramework zkClient;

    /**
     * 判断节点是否存在
     *
     * @param path
     *
     * @return true-存在 false-不存在
     */
    @Override
    public boolean isExistNode(String path) {
        zkClient.sync();
        try {
            Stat stat = zkClient.checkExists().forPath(path);
            return stat != null;
        } catch (Exception e) {
            log.error("isExistNode error!", e);
            throw new RuntimeException("isExistNode error!", e);
        }
    }

    /**
     * 创建节点
     *
     * @param mode
     * @param path
     */
    @Override
    public void createNode(CreateMode mode, String path) {
        try {
            zkClient.create().creatingParentsIfNeeded().withMode(mode).forPath(path);
        } catch (Exception e) {
            log.error("createNode error!", e);
            throw new RuntimeException("createNode error!", e);
        }
    }

    /**
     * 设置节点数据
     *
     * @param path
     * @param nodeData
     */
    @Override
    public void setNodeData(String path, String nodeData) {
        try {
            zkClient.setData().forPath(path, nodeData.getBytes("UTF-8"));
        } catch (Exception e) {
            log.error("setNodeData error!", e);
            throw new RuntimeException("setNodeData error!", e);
        }
    }

    /**
     * 创建/更新节点及其节点数据
     *
     * @param path
     * @param nodeData
     */
    @Override
    public void updateNodeAndData(String path, String nodeData) {
        try {
            if (isExistNode(path)) {
                //节点存在
                setNodeData(path, nodeData);
            } else {
                //节点不存在
                zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, nodeData.getBytes("UTF-8"));
            }
        } catch (Exception e) {
            log.error("updateNodeAndData error!", e);
            throw new RuntimeException("updateNodeAndData error!", e);
        }
    }

    /**
     * 获取节点数据
     *
     * @param path
     */
    @Override
    public String getNodeData(String path) {
        try {
            return new String(zkClient.getData().forPath(path), "UTF-8");
        } catch (Exception e) {
            log.error("getNodeData error!", e);
            throw new RuntimeException("getNodeData error!", e);
        }
    }

    /**
     * 获取节点下子节点
     *
     * @param path
     */
    @Override
    public List<String> getNodeChild(String path) {
        try {
            return zkClient.getChildren().forPath(path);
        } catch (Exception e) {
            log.error("getNodeChild error!", e);
            throw new RuntimeException("getNodeChild error!", e);
        }
    }

    /**
     * 是否递归删除节点
     *
     * @param path
     * @param recursive
     */
    @Override
    public void deleteNode(String path, Boolean recursive) {
        try {
            if (recursive) {
                // 递归删除节点,guaranteed()保障机制,若未删除成功,会话有效期内一直尝试删除
                zkClient.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
            } else {
                // 删除单个节点
                zkClient.delete().guaranteed().forPath(path);
            }
        } catch (Exception e) {
            log.error("deleteNode error!", e);
            throw new RuntimeException("deleteNode error!", e);
        }
    }

}

推荐一篇:Spring Boot 使用 Curator 操作 ZooKeeper_一叶知秋V的博客-CSDN博客

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值