配置服务
配置服务是构建分布式应用所需的基本服务之一,配置服务可以让分布式应用检索和更新配置文件,我编写了一个配置服务的小例子供大家参考使用。
运行环境:
- elipse
- jdk(我用的是jdk1.8)
- ZooKeeper集群(结构请参考我的另一篇文章:https://blog.csdn.net/weixin_37624828/article/details/83750468)
代码
整个服务由三个类构成:
- ConfigDemo.java – 程序入口
- ConfigStore.java --配置文件的仓库
- ConnectionWatcher.java – 连接观察
- ConfigDemo.java
import java.io.IOException;
import org.apache.zookeeper.KeeperException;
public class ConfigDemo {
/**
* 示例入口
* @param args
* @throws IOException
* @throws InterruptedException
* @throws KeeperException
*/
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
//Zookeeper集群主机IP地址和端口号
String hosts = "192.168.225.100:2181,192.168.225.101:2181,192.168.225.102:2181";
//创建配置文件仓库
ConfigStore cs = new ConfigStore();
ConfigDemo configDemo = new ConfigDemo();
//连接集群
cs.connect(hosts);
//例如添加两个元素username和password
configDemo.write(cs, "para", "username", "root");
configDemo.write(cs, "para", "password", "111111");
//读取刚才添加的两个元素的值
System.out.println(configDemo.read(cs, "para", "username"));
System.out.println(configDemo.read(cs, "para", "password"));
}
/**
* 读取元素的值
* @param cs
* @param fileName 配置文件名
* @param key 元素名
* @return
* @throws KeeperException
* @throws InterruptedException
*/
private String read(ConfigStore cs, String fileName, String key) throws KeeperException, InterruptedException {
String path = "/" + fileName + "/" + key;
return cs.read(path, null);
}
/**
* 添加元素
* @param cs
* @param fileName 配置文件名
* @param key 元素名
* @param value 元素值
* @throws KeeperException
* @throws InterruptedException
*/
private void write(ConfigStore cs, String fileName, String key, String value) throws KeeperException, InterruptedException {
cs.write(fileName, key, value);
}
}
- ConfigStore.java
import java.nio.charset.Charset;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
import com.css.test.zk.ConnectionWatcher;
public class ConfigStore extends ConnectionWatcher{
//字符集编码方式
private static final Charset CHARSET = Charset.forName("UTF-8");
/**
* 将元素添加至集群中
* @param fileName 配置文件名
* @param key 元素名
* @param value 元素值
* @throws KeeperException
* @throws InterruptedException
*/
public void write(String fileName, String key, String value) throws KeeperException, InterruptedException {
String path = "/" + fileName;
Stat stat = zk.exists(path, false);
if (stat == null){
zk.create(path, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
path = "/" + fileName + "/" + key;
stat = zk.exists(path, false);
if (stat == null) {
zk.create(path, value.getBytes(CHARSET), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} else {
zk.setData(path, value.getBytes(CHARSET), -1);
}
}
/**
* 从集群中读取元素
* @param path
* @param watcher
* @return
* @throws KeeperException
* @throws InterruptedException
*/
public String read(String path, Watcher watcher) throws KeeperException, InterruptedException {
byte[] data = zk.getData(path, watcher, null);
return new String(data, CHARSET);
}
}
- ConnectionWatcher.java
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
public class ConnectionWatcher implements Watcher {
private static final int SESSION_TIMEOUT = 5000;
protected ZooKeeper zk;
private CountDownLatch connectedSignal = new CountDownLatch(1);
/**
* 连接至ZK集群
* @param hosts
* @throws IOException
* @throws InterruptedException
*/
public void connect(String hosts) throws IOException, InterruptedException {
zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
connectedSignal.await();
}
public void process(WatchedEvent event) {
if (event.getState() == KeeperState.SyncConnected){
connectedSignal.countDown();
}
}
/**
* 断开连接
* @throws InterruptedException
*/
public void close() throws InterruptedException {
zk.close();
}
}
运行测试
新建一个名为para的文件,并向其中添加两个元素(username和password)
修改一个元素的值,并额外另添加一个元素
最后
如果想利用本服务根据自己的分布式应用的具体情况稍作修改即可使用。