IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Zookeeper做配置中心 -> 正文阅读

[大数据]Zookeeper做配置中心

相关命令

 create [-s] [-e] [-c] [-t ttl] path [data] [acl]
 get [-s] [-w] path

[-s] 返回携带元信息
[-w] 添加一个Watcher,一次性的

实现思路

  • 利用zookeeper的持久化节点,保存数据
  • 针对节点,添加watcher,监听 NodeDataChanged 事件

考虑点

  • 每个节点的保存的数据大小有上限,默认为1M,可以通过设置java启动变量进行变更(要先变动服务端、再变动客户端)
// 相关代码
org.apache.jute.BinaryInputArchive#maxBuffer
  • watcher监听在3.6.0版本之前是一次性,而3.6.0版本之后可以添加持续性的watcher
   /**
     * Add a watch to the given znode using the given mode. Note: not all
     * watch types can be set with this method. Only the modes available
     * in {@link AddWatchMode} can be set with this method.
     *
     * @param basePath the path that the watcher applies to
     * @param watcher the watcher
     * @param mode type of watcher to add
     * @throws InterruptedException If the server transaction is interrupted.
     * @throws KeeperException If the server signals an error with a non-zero
     *  error code.
     * @since 3.6.0
     */
    public void addWatch(String basePath, Watcher watcher, AddWatchMode mode)
            throws KeeperException, InterruptedException {
  • 如果客户端与服务端存在网络波动,还是会出现服务端的watcher被触发之后,通知客户端失败(队列里已经没有这个事件了),所以客户端最好建立定时主动查询机制
org.apache.zookeeper.ClientCnxn.EventThread#run 
//  里面的 waitingEvents 队列拿走就没了
  • 如果要配合权限,就在创建节点的时候,设置好 ACL

代码示例实现

  @Bean
    public ZooKeeper zookeeper(ApplicationContext applicationContext) throws IOException, KeeperException, InterruptedException {
        ZKClientConfig zkClientConfig = new ZKClientConfig();
        ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2181", 15000, new CustomConnectWatcher(), zkClientConfig);

        // 360 以上版本,添加持续性的 watcher
        zooKeeper.addWatch("/zk_test", new CustomNodeWatcher370(zooKeeper, applicationContext), AddWatchMode.PERSISTENT_RECURSIVE);
        return zooKeeper;
    }

    @Bean
    public ApplicationConfigProvider applicationConfigProvider(ZooKeeper zookeeper) throws KeeperException, InterruptedException {
        ApplicationConfigProvider applicationConfigProvider = new ApplicationConfigProvider();

        // 3.6.0 以下版本,watcher是一次性的
        //  byte[] data = zookeeper.getData("/zk_test", new CustomNodeWatcher(zookeeper, applicationConfigProvider), null);

        // 3.6.0 以上版本,不需要在手动添加 watcher,在zookeeper初始化时添加一次就行
        byte[] data = zookeeper.getData("/zk_test", false, null);

        applicationConfigProvider.refresh(new String(data));
        return applicationConfigProvider;
    }

	@Slf4j
	@Component
	public class ConsoleOutput {
	
	    @Autowired
	    ApplicationConfigProvider applicationConfigProvider;
	
	    @Scheduled(fixedDelay = 5 * 1000L, initialDelay = 5 * 1000L)
	    public void print() {
	        log.info("目前配置为 :{}", applicationConfigProvider.getMysqlPassword());
	    }
	}
	
	@Slf4j
	public class CustomNodeWatcher370 implements Watcher {
	
	    private ZooKeeper zooKeeper;
	    private ApplicationContext applicationContext;
	
	    public CustomNodeWatcher370(ZooKeeper zooKeeper, ApplicationContext applicationContext) {
	        this.zooKeeper = zooKeeper;
	        this.applicationContext = applicationContext;
	    }
	
		    @SneakyThrows
		    @Override
		    public void process(WatchedEvent event) {
		        if (Objects.equals(event.getType(), Event.EventType.NodeDataChanged)) {
		            // 3.6.0 以上版本,不需要手动再添加 watcher
		            byte[] data = zooKeeper.getData(event.getPath(), false, null);
		            applicationContext.getBean(ApplicationConfigProvider.class).refresh(new String(data));
		        }
		
		    }
		}


	@Slf4j
	public class CustomNodeWatcher implements Watcher {
	
	    private ZooKeeper zooKeeper;
	    private ApplicationConfigProvider applicationConfigProvider;
	
	    public CustomNodeWatcher(ZooKeeper zooKeeper, ApplicationConfigProvider applicationConfigProvider) {
	        this.zooKeeper = zooKeeper;
	        this.applicationConfigProvider = applicationConfigProvider;
	    }
	
	    @SneakyThrows
	    @Override
	    public void process(WatchedEvent event) {
	        if (Objects.equals(event.getType(), Event.EventType.NodeDataChanged)) {
	            byte[] data = zooKeeper.getData(event.getPath(), new CustomNodeWatcher(zooKeeper, applicationConfigProvider), null);
	            applicationConfigProvider.refresh(new String(data));
	        }
	
	    }
	}

原命令操作实例

  • 我们看到目前节点(/zk_test) 的数据为 “香槟不好喝”,数据版本号为 13
    在这里插入图片描述
  • 我们在 get 命令里,同时添加了一个 watcher
  • 重新设置节点数据,发现 watcher 被触发
    在这里插入图片描述
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章           查看所有文章
加:2021-07-26 12:08:54  更:2021-07-26 12:12:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/25 22:22:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码