Curator框架简要解析(一)curator连接zk客户端

curator创建zookeeper客户端代码如下:

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);

        CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181",
                5000,5000,retryPolicy);


        client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {

            }
        });


        client.start();

上述代码是大家经常看见的使用curator框架进行创建zookeeper客户端的过程。主要使用的是CuratorFrameworkFactory#newClient方法进行创建zookeeper的客户端

小园子通过源码下载,查询看到CuratorFrameworkFactory#newClient方法的源码如下:

  public static CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy)
    {
        return builder().
            connectString(connectString).
            sessionTimeoutMs(sessionTimeoutMs).
            connectionTimeoutMs(connectionTimeoutMs).
            retryPolicy(retryPolicy).
            build();
    }


/**
 点击build()方法代码如下

**/
 public CuratorFramework build() {
     return new CuratorFrameworkImpl(this);
 }

看上述代码是通过一个构造器进行创建了一个CuratorFrameworkImpl对象,然后我们进行查看CuratorFrameworkImpl的构造函数发现,会将创建时候的参数进行一些赋值的操作,里面有一些比较重要的逻辑比方说:

ZookeeperFactory localZookeeperFactory = makeZookeeperFactory(builder.getZookeeperFactory());

第一步就进行创建了zookeeper的工厂方法,我们可以大胆的猜测是通过这个工厂进行创建zookeeper的客户端。

再比如: listeners = new ListenerContainer<CuratorListener>();

这个listeners的创建。这个我们后面再进行分析的操作,我们先继续看在哪里进行创建的zookeeper的客户端,在这里没看到有zookeeper客户端的创建。

 public CuratorFrameworkImpl(CuratorFrameworkFactory.Builder builder)
    {
        ZookeeperFactory localZookeeperFactory = makeZookeeperFactory(builder.getZookeeperFactory());
        this.client = new CuratorZookeeperClient
            (
                localZookeeperFactory,
                builder.getEnsembleProvider(),
                builder.getSessionTimeoutMs(),
                builder.getConnectionTimeoutMs(),
                builder.getWaitForShutdownTimeoutMs(),
                new Watcher()
                {
                    @Override
                    public void process(WatchedEvent watchedEvent)
                    {
                        CuratorEvent event = new CuratorEventImpl(CuratorFrameworkImpl.this, CuratorEventType.WATCHED, watchedEvent.getState().getIntValue(), unfixForNamespace(watchedEvent.getPath()), null, null, null, null, null, watchedEvent, null, null);
                        processEvent(event);
                    }
                },
                builder.getRetryPolicy(),
                builder.canBeReadOnly(),
                builder.getConnectionHandlingPolicy()
            );

        internalConnectionHandler = new StandardInternalConnectionHandler();
        listeners = new ListenerContainer<CuratorListener>();
        unhandledErrorListeners = new ListenerContainer<UnhandledErrorListener>();
        backgroundOperations = new DelayQueue<OperationAndData<?>>();
        forcedSleepOperations = new LinkedBlockingQueue<>();
        namespace = new NamespaceImpl(this, builder.getNamespace());
        threadFactory = getThreadFactory(builder);
        maxCloseWaitMs = builder.getMaxCloseWaitMs();
        connectionStateManager = new ConnectionStateManager(this, builder.getThreadFactory(), builder.getSessionTimeoutMs(), builder.getConnectionHandlingPolicy().getSimulatedSessionExpirationPercent(), builder.getConnectionStateListenerDecorator());
        compressionProvider = builder.getCompressionProvider();
        aclProvider = builder.getAclProvider();
        state = new AtomicReference<CuratorFrameworkState>(CuratorFrameworkState.LATENT);
        useContainerParentsIfAvailable = builder.useContainerParentsIfAvailable();
        connectionStateErrorPolicy = Preconditions.checkNotNull(builder.getConnectionStateErrorPolicy(), "errorPolicy cannot be null");
        schemaSet = Preconditions.checkNotNull(builder.getSchemaSet(), "schemaSet cannot be null");
        zk34CompatibilityMode = builder.isZk34CompatibilityMode();

        byte[] builderDefaultData = builder.getDefaultData();
        defaultData = (builderDefaultData != null) ? Arrays.copyOf(builderDefaultData, builderDefaultData.length) : new byte[0];
        authInfos = buildAuths(builder);

        failedDeleteManager = new FailedDeleteManager(this);
        failedRemoveWatcherManager = new FailedRemoveWatchManager(this);
        namespaceFacadeCache = new NamespaceFacadeCache(this);

        ensembleTracker = zk34CompatibilityMode ? null : new EnsembleTracker(this, builder.getEnsembleProvider());

        runSafeService = makeRunSafeService(builder);
    }

在上述的代码中我们没有找zookeeper客户端的创建操作的代码信息,那么我们猜测只能是在

client.start();

这个方法执行的时候,进行创建zookeepe的客户端,我们点击这个start方法进去看下,由上面的代码逻辑,我们可以看出来client对象为CuratorFrameworkImpl对象,那么我们就直接进行查看CuratorFrameworkImpl#start方法就可以了,其代码如下:

   @Override
    public void start()
    {
        log.info("Starting");
        if ( !state.compareAndSet(CuratorFrameworkState.LATENT, CuratorFrameworkState.STARTED) )
        {
            throw new IllegalStateException("Cannot be started more than once");
        }

        try
        {
            connectionStateManager.start(); // ordering dependency - must be called before client.start()

            final ConnectionStateListener listener = new ConnectionStateListener()
            {
                @Override
                public void stateChanged(CuratorFramework client, ConnectionState newState)
                {
                    if ( ConnectionState.CONNECTED == newState || ConnectionState.RECONNECTED == newState )
                    {
                        logAsErrorConnectionErrors.set(true);
                    }
                }

                @Override
                public boolean doNotDecorate()
                {
                    return true;
                }
            };

            this.getConnectionStateListenable().addListener(listener);

            client.start();

            executorService = Executors.newSingleThreadScheduledExecutor(threadFactory);
            executorService.submit(new Callable<Object>()
            {
                @Override
                public Object call() throws Exception
                {
                    backgroundOperationsLoop();
                    return null;
                }
            });

            if ( ensembleTracker != null )
            {
                ensembleTracker.start();
            }

            log.info(schemaSet.toDocumentation());
        }
        catch ( Exception e )
        {
            ThreadUtils.checkInterrupted(e);
            handleBackgroundOperationException(null, e);
        }
    }

在上面的代码中,我们发现了ConnectionStateManager对象的start方法,CuratorZookeeperClient对象的start方法,连接状态的监听器的添加,以及提交一个异步线程任务等。

我们就接着看ConnectionStateManager对象的start方法

   public void start()
    {
        Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");

        service.submit
            (
                new Callable<Object>()
                {
                    @Override
                    public Object call() throws Exception
                    {
                        processEvents();
                        return null;
                    }
                }
            );
    }

从上面的代码中没看到什么有用的信息,我们暂时先放过,我们继续看CuratorZookeeperClient对象的start方法,感觉应该是在这个方法中进行创建zookeeper客户端的操作了

 public void start() throws Exception
    {
        log.debug("Starting");

        if ( !started.compareAndSet(false, true) )
        {
            throw new IllegalStateException("Already started");
        }
        //这里的state对象为ConnectionState类的对象
        state.start();
    }

这里有一个cas的操作和ConnectionState对象的start方法,那我们就继续看ConnectionState对象的start方法

  void start() throws Exception
    {
        log.debug("Starting");
//通过上下文,可以看出这里的对象为FixedEnsembleProvider对象
//再查看FixedEnsembleProvider的start方法,发现里面空空如也
        ensembleProvider.start();
        reset();
    }

我们进行查询reset方法就可以看到如下代码:

    synchronized void reset() throws Exception
    {
        log.debug("reset");

        instanceIndex.incrementAndGet();

        isConnected.set(false);
        connectionStartMs = System.currentTimeMillis();
        zooKeeper.closeAndReset();
        zooKeeper.getZooKeeper();   // initiate connection
    }

 可以看出来主要方法就在zooKeeper.getZooKeeper()方法中,在点击进去就看到如下的代码逻辑:

  void closeAndReset() throws Exception {
        this.internalClose(0);
        this.helper = new Helper() {
            private volatile ZooKeeper zooKeeperHandle = null;
            private volatile String connectionString = null;

            public ZooKeeper getZooKeeper() throws Exception {
                synchronized(this) {
                    if (this.zooKeeperHandle == null) {
                        this.connectionString = HandleHolder.this.ensembleProvider.getConnectionString();
                        this.zooKeeperHandle = HandleHolder.this.zookeeperFactory.newZooKeeper(this.connectionString, HandleHolder.this.sessionTimeout, HandleHolder.this.watcher, HandleHolder.this.canBeReadOnly);
                    }

                    HandleHolder.this.helper = new Helper() {
                        public ZooKeeper getZooKeeper() throws Exception {
                            return zooKeeperHandle;
                        }

                        public String getConnectionString() {
                            return connectionString;
                        }

                        public int getNegotiatedSessionTimeoutMs() {
                            return zooKeeperHandle != null ? zooKeeperHandle.getSessionTimeout() : 0;
                        }
                    };
                    return this.zooKeeperHandle;
                }
            }

我们从中不难发现是通过使用HandleHolder.this.zookeeperFactory.newZooKeeper(this.connectionString, HandleHolder.this.sessionTimeout, HandleHolder.this.watcher, HandleHolder.this.canBeReadOnly);我们就开始在源码中进行追踪这个 zookeeperFactory到底是什么东西,通过代码的追踪,我们发现是CuratorFrameworkImpl对象初始化的时候第一行代码

ZookeeperFactory localZookeeperFactory = makeZookeeperFactory(builder.getZookeeperFactory());

那我们就直接从makeZookeeperFactory中进行找寻创建连接zookeeper客户端的代码,发现其代码也是简洁明了,我们一眼就看出了如何进行创建连接客户端的操作

    private ZookeeperFactory makeZookeeperFactory(final ZookeeperFactory actualZookeeperFactory)
    {
        return new ZookeeperFactory()
        {
            @Override
            public ZooKeeper newZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly) throws Exception
            {
                ZooKeeper zooKeeper = actualZookeeperFactory.newZooKeeper(connectString, sessionTimeout, watcher, canBeReadOnly);
                for ( AuthInfo auth : authInfos )
                {
                    zooKeeper.addAuthInfo(auth.getScheme(), auth.getAuth());
                }

                return zooKeeper;
            }
        };
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小园子的小菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值