springboot实现zookeeper统一配置中心

        配置文件比如数据库连接,缓存更新时间,接口调用地址,加解密密钥,sesion超时时间,等等每个项目里面用的太多,如果项目里面都统一放在一个properties文件里面,会出现的问题,就是一旦一个地方修改了,假如有10台机器或者上百台,那么就需要重新部署这10台或者上百台的服务器,有没有更好的方法来管理配置文件?有,目前用的比较多的就是使用zookeeper,目前我还没仔细阅读过zookeeper的源码,不过实际使用已经做过测试,这里分享一下,如何在springboot项目里面使用zookeeper实现统一的配置中心。

        1.添加依赖

        我使用了最新的客户端curator 5.1.0,可以在mvn仓库里面找 ,https://mvnrepository.com

        

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

		<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>5.1.0</version>
		</dependency>

       

       2.写Component

       

/**
 * 
 */
package com.figo.springboottest.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.annotation.PostConstruct;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
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.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Component;

/**
 * ZooKeeper统一配置中心
 * 
 * @author figo
 * @since 20200722
 */
@Component
public class ZooKeeperConfig {
	// 这里缓存可以换成redis
	private Map<String, String> cache = new HashMap<>();
	private CuratorFramework client;
	private static final String CONFIG_PREFIX = "/CONFIG";

	// 初始化zk连接
//	public ZooKeeperConfig() {
//		this.client = CuratorFrameworkFactory.newClient("150.158.158.198:2181", new RetryNTimes(3, 1000));
//		this.client.start();
//		this.init();
//	}
	/**
	 * 构造函数 .
	 */
	@PostConstruct
	public void init() {
		try {
			this.client = CuratorFrameworkFactory.newClient("150.158.158.198:2181", new RetryNTimes(3, 1000));
			this.client.start();
			// 从zk中获取配置项并保存到缓存中
			List<String> childrenNames = client.getChildren().forPath(CONFIG_PREFIX);
			for (String name : childrenNames) {
				String value = new String(client.getData().forPath(CONFIG_PREFIX + "/" + name));
				cache.put(name, value);
			}
			// 绑定一个监听器 cacheData设为true,事件发生后可以拿到节点发送的内容。
			// 使用该配置文件的每个应用机器都需要监听
			PathChildrenCache watcher = new PathChildrenCache(client, CONFIG_PREFIX, true);
			watcher.getListenable().addListener(new PathChildrenCacheListener() {

				@Override
				public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event)
						throws Exception {

					String path = event.getData().getPath();
					if (path.startsWith(CONFIG_PREFIX)) {
						String key = path.replace(CONFIG_PREFIX + "/", "");
						// 子节点新增或变更时 更新缓存信息
						if (PathChildrenCacheEvent.Type.CHILD_ADDED.equals(event.getType())
								|| PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(event.getType())) {
							System.out.println("event.getType()=" + event.getType() + ",key=" + key + ",value="
									+ new String(event.getData().getData()));
							cache.put(key, new String(event.getData().getData()));
						}
						// 子节点被删除时 从缓存中删除
						if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(event.getType())) {
							System.out.println("event.getType()=" + event.getType() + ",key=" + key + ",value="
									+ new String(event.getData().getData()));
							cache.remove(key);
						}
					}
				}
			});
			watcher.start();

			/**
			 * 这里换成TreeCache也是一样的
			 */
			/**
			 * TreeCache treeCache = new TreeCache(client, CONFIG_PREFIX); // 监听属性值变更
			 * treeCache.getListenable().addListener(new TreeCacheListener() {
			 * 
			 * @Override public void childEvent(CuratorFramework curatorFramework,
			 *           TreeCacheEvent treeCacheEvent) throws Exception { if
			 *           (Objects.equals(treeCacheEvent.getType(),
			 *           TreeCacheEvent.Type.NODE_ADDED) ||
			 *           Objects.equals(treeCacheEvent.getType(),
			 *           TreeCacheEvent.Type.NODE_UPDATED)) { String updateKey =
			 *           treeCacheEvent.getData().getPath().replace(CONFIG_PREFIX + "/",
			 *           ""); System.out.println("数据更新: "+treeCacheEvent.getType()+",
			 *           key:"+updateKey+",value:"+new
			 *           String(treeCacheEvent.getData().getData())); } } });
			 **/

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

	// 保存配置信息
	public void save(String name, String value) {
		String configFullName = CONFIG_PREFIX + "/" + name;
		try {
			Stat stat = client.checkExists().forPath(configFullName);
			if (stat == null) {
				client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(configFullName,
						value.getBytes());
			} else {
				client.setData().forPath(configFullName, value.getBytes());
			}
			cache.put(name, value);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// 获取配置信息
	public String get(String name) {
		return cache.get(name);
	}
}

3.连上zookeeper客户端进行测试

//集群有3个节点,连上任何一个节点都可以

[root@VM_0_7_centos bin]# ./zkCli.sh -server 127.0.0.1:2181

[zk: 127.0.0.1:2181(CONNECTED) 2] create /CONFIG/zknode_000001 test
Created /CONFIG/zknode_000001
[zk: 127.0.0.1:2181(CONNECTED) 3] set /CONFIG/zknode_000001 test123
[zk: 127.0.0.1:2181(CONNECTED) 4] delete /CONFIG/zknode_000001

[zk: 127.0.0.1:2181(CONNECTED) 2] create /CONFIG/zknode_000002 hello,world
Created /CONFIG/zknode_000002

监听代码里面,日志可以看到实时侦听到增删改的变动了

event.getType()=CHILD_ADDED,key=zknode_000001,value=test
event.getType()=CHILD_UPDATED,key=zknode_000001,value=test123
event.getType()=CHILD_REMOVED,key=zknode_000001,value=test123

event.getType()=CHILD_ADDED,key=zknode_000002,value=hello,world

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值