ZooKeeperNet源码解析

转载请注明出处:jiq•钦's technical Blog
ZooKeeperNet是ZooKeeper的.NET客户端,下载地址:https://github.com/ewhauser/zookeeper

测试程序

ZooKeeper zkClient = new ZooKeeper(URL,new TimeSpan(0, 0, 0, 10000), watcher);

if(zkClient.Exists("/config/configJ",null) ==null)

{

   zkClient.Create("/config/configJ", json.GetBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);

}

 

初始化和启动

首先看ZooKeeper构造函数:

public ZooKeeper(string connectstring,TimeSpan sessionTimeout, IWatcherwatcher, long sessionId, byte[] sessionPasswd)

       {

            LOG.Info(string.Format("Initiating client connection, connectstring={0}sessionTimeout={1} watcher={2} sessionId={3} sessionPasswd={4}",connectstring, sessionTimeout, watcher, sessionId, (sessionPasswd == null ? "<null>": "<hidden>")));

 

         //之后连接状态发生变化后会放入ClientConnectionEventConsumer回调

            watchManager.defaultWatcher =watcher;

            cnxn = newClientConnection(connectstring,sessionTimeout,this, watchManager, sessionId,sessionPasswd);

            cnxn.Start();

       }

 

创建了一个ClientConnection对象,继续看其构造函数:

public ClientConnection(string hosts,TimeSpan sessionTimeout, ZooKeeperzooKeeper, ZKWatchManager watcher,long sessionId, byte[]sessionPasswd)

       {

            this.hosts= hosts;

            this.zooKeeper= zooKeeper;

            this.watcher= watcher;

            SessionTimeout = sessionTimeout;

            SessionId = sessionId;

            SessionPassword = sessionPasswd;

 

            // parseout chroot, if any

            hosts = SetChrootPath();

            GetHosts(hosts);

            SetTimeouts(sessionTimeout);

            CreateConsumer();

            CreateProducer();

       }

 

关键是看最后两句代码,实现代码为:

private void CreateConsumer()

       {

            consumer = newClientConnectionEventConsumer(this);

       }

 

       private voidCreateProducer()

       {

            producer = newClientConnectionRequestProducer(this);

       }

 

这两个是什么东西?

(1)先看ClientConnectionEventConsumer

public ClientConnectionEventConsumer(ClientConnectionconn)

       {

            this.conn= conn;

            eventThread = new Thread(new SafeThreadStart(PollEvents).Run){ Name ="ZK-EventThread " +conn.zooKeeper.Id, IsBackground =true };

       }

 

创建了一个线程,线程的主体是:

public void PollEvents()

       {

            try

            {

                while(!waitingEvents.IsCompleted)

                {

                    object@event = waitingEvents.Take();

                    try

                    {

                        if (@eventis ClientConnection.WatcherSetEventPair)

                        {

                            // each watcher will process the event

                            ClientConnection.WatcherSetEventPairpair = (ClientConnection.WatcherSetEventPair) @event;

                            foreach (IWatcherwatcherin pair.watchers)

                            {

                                try

                                {

                                   watcher.Process(pair.@event);

                                }

                                catch (Exceptiont)

                               {

                                    LOG.Error("Error while calling watcher ", t);

                                }

                            }

                        }

                    }

                    catch(OperationCanceledException)

                    {

                        //ignored

                    }

                    catch(Exception t)

                    {

                        LOG.Error("Caught unexpected throwable", t);

                    }

                }

            }

            catch(ThreadInterruptedException e)

            {

                LOG.Error("Event thread exiting due to interruption",e);

            }

 

            LOG.Info("EventThreadshut down");

       }

 

核心代码作用是不断从waitingEvents中取出@event,将其中的IWatcher的process函数通通调用一遍,看来ClientConnectionEventConsumer的作用是维护IWatcher集合,并调用它们对应的事件响应函数,至于事件是如何add到waitingEvents中的,稍后再看。

 

(2)在看看ClientConnectionRequestProducer

public ClientConnectionRequestProducer(ClientConnectionconn)

       {

            this.conn= conn;

            zooKeeper = conn.zooKeeper;

            requestThread = new Thread(new SafeThreadStart(SendRequests).Run){ Name ="ZK-SendThread" +conn.zooKeeper.Id, IsBackground =true };

       }

 

同样创建了一个线程,线程的主体是:

public void SendRequests()

       {

            DateTimenow = DateTime.Now;

            DateTimelastHeard = now;

            DateTimelastSend = now;

 

            //state != CLOSED && state != AUTH_FAILED循环

            while(zooKeeper.State.IsAlive())

            {

                try

                {

                    //TcpClient是否为空

                    if(client == null)

                    {

                        // don't re-establish connection if we are closing

                        if (conn.closing)

                        {

                            break;

                        }

 

                        StartConnect(); //建立到ZookeeperTCP连接

                        lastSend = now;

                        lastHeard = now;

                    }

 

                    //若还未变为CONNECTED状态,判断是否超时

                    TimeSpanidleRecv = now - lastHeard;

                    TimeSpanidleSend = now - lastSend;

                    TimeSpanto = conn.readTimeout - idleRecv;

                    if(zooKeeper.State !=ZooKeeper.States.CONNECTED)

                    {

                        to =conn.connectTimeout - idleRecv;

                    }

                    if(to <= TimeSpan.Zero)

                    {

                        throw new SessionTimeoutExceptio

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值