public void Connect() { zk = new ZooKeeper(zookeeperAddress, new TimeSpan(0, 0, timeout), this); Console.WriteLine("Waiting for Zookeeper to connect..."); connected.WaitOne(); zk.Register(treeWatcher); //Disconnect(); //int tries = retries; //while ((tries--) > 0) //{ // try // { // zk = new ZooKeeper(zookeeperAddress, new TimeSpan(0, 0, timeout), treeWatcher); // isDisposed = false; // break; // } // catch (Exception ex) // { // if (tries == 0) // { // Console.WriteLine("Creating new zookeeper exception after #" + retries + "retrues :\n" + ex.Message); // Console.WriteLine("Last retry, throwing exception"); // throw ex; // } // } // if (zk != null) // { // break; // } //} }
public void waitForLock(String lower) { zk.Register(new LockerCommon()); //监听比自己次小的节点 Stat stat = zk.Exists(root + "/" + lower, true); if (stat != null) { Console.WriteLine($"Waiting for {lower}"); } else { var t = DateTime.Now; Console.WriteLine($"{ourPath}访问资源,时间为{DateTime.Now}"); //访问共享资源 IsGetLock(); //释放锁 Console.WriteLine($"访问结束{(DateTime.Now - t).TotalMilliseconds}"); try { zk.Delete(ourPath, -1); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine($"{ourPath}已被删除,时间为{DateTime.Now}"); Console.ReadLine(); } }
public void GetLock() { var parent = OurPath.Substring(0, OurPath.LastIndexOf('/')); var nodes = ZK.GetChildren(parent, false).ToList(); nodes.Sort(); if (OurPath.Equals(parent + "/" + nodes[0])) { HasGetLock = true; monitor.Set(); } else { //注册watch if (ZK.Exists(OurPath, false) != null) { ZK.Register(new Locker(ZK, OurPath)); } var myNode = OurPath.Substring(OurPath.LastIndexOf('/') + 1); var lower = string.Empty; for (int i = 0; i < nodes.Count; i++) { if (nodes[i].Equals(myNode)) { lower = nodes[i - 1]; } } WaitForLock(parent + "/" + lower); HasGetLock = false; } }
public static void Watch() { // 这里注册的 watch 实例会覆盖 new Zookeeper() 时指定的 watch 实例 // 如果注册多个,则会把最后注册的覆盖之前注册的 zk.Register(new WatchCommon(zk)); zk.Register(new WatchCommon3(zk)); // 3 种添加 watch 的方式 Stat stat = new Stat(); // 1. 这种方式增加 watch ,只能watch 此节点的数据更新和删除事件 zk.GetData("/test/t1", true, stat); // /test/t1 要事先存在 zk.GetData("/test/t2", new WatchCommon(zk), stat); // 单独指定实例,不使用 注册时的实例 /test/t2 要事先存在 // 2. 这种方式增加 watch ,可以watch 此节点的数据更新和删除事件,以及节点创建事件 zk.Exists("/test/t3", true); // /test/t3 可事先不存在 // 3. 这种方式增加的 watch, 可以 watch 此节点的删除事件,以及子节点的创建和删除事件 zk.GetChildren("/test/t3", true); // /test/t3 要事先存在 /* * 上面 语句 zk.Exists("/test/t3", true); 和 zk.GetChildren("/test/t3", true); watch 中都包含 删除事件, * 那如果把 /test/t3 删除,是否会收到两次通知呢? * 测试结果是只收到一次通知,因为 watch 实例是一样的, * 如果 后面的语句改成 zk.GetChildren("/test/t3", new WatchCommon2()); 即单独的 watch 实例, * 则把 /test/t3 删除,每个实例都会收到通知 */ /* 注意点: * 1.watch是一次性触发的,如果获取一个watch事件并希望得到新变化的通知,需要重新设置watch * 2.watch是一次性触发的并且在获取watch事件和设置新watch事件之间有延迟,所以不能可靠的观察到节点的每一次变化。要认识到这一点。 */ var childWatchList = zk.ChildWatches; var dataWatchList = zk.DataWatches; var existWatchList = zk.ExistWatches; }
public void Register(IWatcher watcher) { int tries = retries; while ((tries--) > 0) { try { zk.Register(watcher); break; } catch (Exception ex) { if (tries == 0) { Console.WriteLine("Register exception after #" + retries + " retries :\n" + ex.Message); Console.WriteLine("Last retry, throwing exception"); throw ex; } } } }
public void watch(string path) { Configuration = System.Text.Encoding.Default.GetString(zk.GetData(path, false, null)); zk.Register(new Watch()); System.Text.Encoding.Default.GetString(zk.GetData(path, true, null)); }