1. 程式人生 > >配置服務(基於ZooKeeper叢集的配置服務)

配置服務(基於ZooKeeper叢集的配置服務)

配置服務

配置服務是構建分散式應用所需的基本服務之一,配置服務可以讓分散式應用檢索和更新配置檔案,我編寫了一個配置服務的小例子供大家參考使用。

執行環境:

  1. elipse
  2. jdk(我用的是jdk1.8)
  3. ZooKeeper叢集(結構請參考我的另一篇文章:https://blog.csdn.net/weixin_37624828/article/details/83750468)

程式碼
整個服務由三個類構成:

  1. ConfigDemo.java – 程式入口
  2. ConfigStore.java --配置檔案的倉庫
  3. 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)
在這裡插入圖片描述
修改一個元素的值,並額外另新增一個元素
在這裡插入圖片描述

最後

如果想利用本服務根據自己的分散式應用的具體情況稍作修改即可使用。