看了一些例子 代码都很长 于是简单尝试了下
竞争选举 就是看谁快 谁先声明自己为Leader
简单贴点代码,未加粗的地方可以忽略 大概看思路
首先,创建监视节点 /overseer
protected void CreateCommonNode()
{
//live_nodes node
var stat = zooKeeper.Exists("/live_nodes", false);
if (stat == null)
zooKeeper.Create("/live_nodes", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/live_nodes/crawler", false);
if (stat == null)
zooKeeper.Create("/live_nodes/crawler", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/live_nodes/extracter", false);
if (stat == null)
zooKeeper.Create("/live_nodes/extracter", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/live_nodes/proxy", false);
if (stat == null)
zooKeeper.Create("/live_nodes/proxy", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
//config node
stat = zooKeeper.Exists("/config", false);
if (stat == null)
zooKeeper.Create("/config", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/config/crawler", false);
if (stat == null)
zooKeeper.Create("/config/crawler", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/config/extracter", false);
if (stat == null)
zooKeeper.Create("/config/extracter", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/config/proxy", false);
if (stat == null)
zooKeeper.Create("/config/proxy", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/overseer", false);
if (stat == null)
zooKeeper.Create("/overseer", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
stat = zooKeeper.Exists("/overseer/election", false);
if (stat == null)
zooKeeper.Create("/overseer/election", null, Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
}
然后 创建Leader选举方法,这里就是谁先建完了,谁就是Leader,其他会报节点已存在异常
protected void RunForLeaderNode()
{
try
{
var stat = zooKeeper.Exists("/overseer/leader", new LeaderNodeDeleteWatcher(this));
if (stat == null)
{
var d = JsonConvert.SerializeObject(new
{
baseUrl = BaseUrl
});
zooKeeper.Create("/overseer/leader", d.GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Ephemeral);
Console.WriteLine("current leader is " + BaseUrl);
}
}
catch (ZooKeeperNet.KeeperException.NodeExistsException ex)
{
Console.WriteLine(BaseUrl + " run for leader failed!");
}
}
LeaderNodeDeleteWatcher
class LeaderNodeDeleteWatcher : IWatcher
{
NodeBase service;
public LeaderNodeDeleteWatcher(NodeBase service)
{
this.service = service;
}
public void Process(WatchedEvent @event)
{
if(@event.Type == EventType.NodeDeleted)
{
Console.WriteLine("leader offline, run for leader");
service.RunForLeaderNode();
}
}
}
Start方法
public virtual void Start()
{
if (string.IsNullOrEmpty(BaseUrl) || string.IsNullOrEmpty(ZkServer))
throw new Exception("BaseUrl and ZkServer must be set,call setup method!");
var resetEvent = new ManualResetEvent(false);
var watcher = new SessionWatcher(this, resetEvent);
try
{
Console.WriteLine("node " + BaseUrl + " ready to startup!");
Console.WriteLine("try connect to zookeeper server : " + ZkServer);
zooKeeper = new ZooKeeper(ZkServer, TimeSpan.FromSeconds(15), watcher);
resetEvent.WaitOne();
CreateCommonNode();
RunForLeaderNode();
CreateOverseerNode();
OnStartup();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
运行截图
详细代码见 https://github.com/zhupingqi/RuiJi.Net/blob/master/RuiJi.Node/NodeBase.cs