Zookeeper 作為一個分布式的服務框架,主要用來解決分布式集群中應用系統的一致性問題,它能提供基於類似於文件系統的目錄節點樹方式的數據存儲,但是 Zookeeper 並不是用來專門存儲數據的,它的作用主要是用來維護和監控你存儲的數據的狀態變化。通過監控這些數據狀態的變化,從而可以達到基於數據的集群管理。
● 通過C#代碼使用zookeeper
Zookeeper的使用主要是通過創建其Nuget ZooKeeper.Net包下的ZooKeeper實例,並且調用其接口方法進行的,主要的操作就是對znode的增刪改查操作,監聽znode的變化以及處理。
using System; using ZooKeeperNet; namespace ConsoleApplication1 { class Watcher : IWatcher { public void Process(WatchedEvent @event) { if (@event.Type == EventType.NodeDataChanged) { Console.WriteLine(@event.Path + "節點的值被修改"); } } } } using System; using System.Linq; using System.Text; using ZooKeeperNet; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //創建一個Zookeeper實例,第一個參數為目標服務器地址和端口,第二個參數為Session超時時間,第三個為節點變化時的回調方法 using (ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", new TimeSpan(0, 0, 0, 10), new Watcher())) { String znode_root = "/dubbo/com.alibaba.dubbo.demo.SubDemoService/consumers"; var stat = zk.Exists(znode_root, true); if (null == stat) { //創建一個節點root,數據是mydata,不進行ACL權限控制,節點為永久性的(即客戶端shutdown了也不會消失) zk.Create(znode_root, "mydata".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent); } else { var data1 = zk.GetData(znode_root, true, null); Console.WriteLine(znode_root + ":" + Encoding.Default.GetString(data1)); } //在root下面創建一個child1 znode,數據為child1,不進行ACL權限控制,節點為永久性的 string c = zk.Create("/root/child1", "child1".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent); Console.WriteLine(c); //取得/root節點下的子節點名稱,返回List<String> var childrenNodes = zk.GetChildren("/root", true); Console.WriteLine("子節點個數:"+childrenNodes.Count()); //取得/root/child1節點下的數據,返回byte[] byte[] data = zk.GetData("/root/child1", true, null); Console.WriteLine("節點存儲的數據:"+Encoding.Default.GetString(data)); //修改節點/root/child1下的數據,第三個參數為版本,如果是-1,那會無視被修改的數據版本,直接改掉 zk.SetData("/root/child1", "child1modify".GetBytes(), -1); //刪除/root/child1這個節點,第二個參數為版本,-1的話直接刪除,無視版本 zk.Delete("/root/child1", -1); } Console.Read(); } } }
程序運行結果:
/dubbo/com.alibaba.dubbo.demo.SubDemoService/consumers:192.168.40.69 /root/child1 子節點個數:3 節點存儲的數據:child1 節點的值被修改:/root/child1
● 通過java代碼使用zookeeper
java的使用方式同樣也是實例化ZooKeeper對象並調用其方法,來操作znode。
zookeeper包依賴:
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
code:
import com.alibaba.fastjson.JSON; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.util.List; import java.util.UUID; public class ZkDemo { public static void main(String[] args) throws Exception { String host = "127.0.0.1:2181"; int timeout = 1000; ZooKeeper zk = new ZooKeeper(host, timeout, new Watcher() { public void process(WatchedEvent watchedEvent) { if (watchedEvent.getType() == Event.EventType.NodeDataChanged) { System.out.println(watchedEvent.getPath() + "節點的值被修改"); } } }); String znode_root = "/dubbo/com.alibaba.dubbo.demo.SubDemoService/consumers"; Stat stat = zk.exists(znode_root, true); if (null == stat) { zk.create(znode_root, "mydata".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println(znode_root + "被創建"); } else { byte[] data = zk.getData(znode_root, true, null); System.out.println(znode_root + ":" + new String(data)); } if(zk.exists("/root/node2",true)==null) { //在root下面創建一個名為node2的znode,數據為node2val,不進行ACL權限控制,節點為永久性的 zk.create("/root/node2", "node2val".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } //取得/root節點下的子節點名稱,返回List<String> List<String> childrenNodes = zk.getChildren("/root", true); System.out.println(String.format("子節點(%s個):%s", childrenNodes.size(), JSON.toJSONString(childrenNodes))); zk.setData("/root/node2", UUID.randomUUID().toString().getBytes(), -1); zk.close(); } }
程序運行結果:
/dubbo/com.alibaba.dubbo.demo.SubDemoService/consumers:192.168.40.69 子節點(2個):["childone","node2"] /root/node2節點的值被修改
● 通過監控管理工具查看zk節點樹