curator源码(一) 初始化、启动和关闭。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjw10wei321/article/details/50384445

Curator框架是zookeeper客户端框架,官网有句话说的很简洁:curator对于zookeeper就像Guava对于java。
重复策略,实例化,众多实用的食谱菜单(分布式锁,计数器,队列,栅栏,信号量,路径缓存)。

初始化

1.直接调用CuratorFrameworkFactory的newClient方法

   /**
     * 创建客户端
     * @param connectString       zk地址
     * @param sessionTimeoutMs    session超时
     * @param connectionTimeoutMs 路径超时
     * @param retryPolicy         重复策略
     * @return client
     */
    public static CuratorFramework newClient(String connectString, int sessionTimeoutMs, 
    int connectionTimeoutMs, RetryPolicy retryPolicy)
    {
        return builder().
            connectString(connectString).
            sessionTimeoutMs(sessionTimeoutMs).
            connectionTimeoutMs(connectionTimeoutMs).
            retryPolicy(retryPolicy).
            build();
    }
    /**
     * 返回一个用来创建CuratorFramework新的builder
     * @return new builder
     */
    public static Builder builder()
    {
        return new Builder();
    }

返回的Builder是CuratorFrameworkFactory的内部类,主要用于流式的创建CuratorFramework,里面包含所需参数

        private EnsembleProvider ensembleProvider;
        private int sessionTimeoutMs = DEFAULT_SESSION_TIMEOUT_MS;
        private int connectionTimeoutMs = DEFAULT_CONNECTION_TIMEOUT_MS;
        private int maxCloseWaitMs = DEFAULT_CLOSE_WAIT_MS;
        private RetryPolicy retryPolicy;
        private ThreadFactory threadFactory = null;
        private String namespace;
        private List<AuthInfo> authInfos = null;
        private byte[] defaultData = LOCAL_ADDRESS;
        private CompressionProvider compressionProvider = DEFAULT_COMPRESSION_PROVIDER;
        private ZookeeperFactory zookeeperFactory = DEFAULT_ZOOKEEPER_FACTORY;
        private ACLProvider aclProvider = DEFAULT_ACL_PROVIDER;
        private boolean canBeReadOnly = false;
        private boolean useContainerParentsIfAvailable = true;

ensembleProvider(配置提供者) 可以通过在Builder里的以下2个方法构造。设置服务器的链接地址,
格式: host:port,host2:port2…..
主要由此提供链接地址,供后期zookeeper里使用。

       public Builder connectString(String connectString)
        {
            ensembleProvider = new FixedEnsembleProvider(connectString);
            return this;
        }

       public Builder ensembleProvider(EnsembleProvider ensembleProvider)
        {
            this.ensembleProvider = ensembleProvider;
            return this;
        }

2.通过Builder的build函数创建客户端。

       /**
         * 根据builder里的值创建新的CuratorFramework
         * @return new CuratorFramework
         */
        public CuratorFramework build()
        {
            return new CuratorFrameworkImpl(this);
        }

3.CuratorFrameworkImpl定义

CuratorFrameworkImpl为CuratorFramework接口的一个实现,平时主要用到的就是此client。
该构造函数主要还是使用Builder里的默认配置的一些参数,这些参数可以通过CuratorFrameworkFactory李的Builder去流式创建。

设置如下参数,如ZookeeperFactory 工厂,CuratorZookeeperClient【重点,客户端的工作主要靠它】,listeners 监听,backgroundOperations 后台运行行为,namespace 命名空间(用于放置在路径的前缀),
threadFactory CuratorFrameworkImpl的线程工厂,connectionStateManager 链接状态管理器, compressionProvider 压缩器等等。

public CuratorFrameworkImpl(CuratorFrameworkFactory.Builder builder)
    {
        ZookeeperFactory localZookeeperFactory = makeZookeeperFactory(builder.getZookeeperFactory());
        this.client = new CuratorZookeeperClient(localZookeeperFactory, builder.getEnsembleProvider(), builder.getSessionTimeoutMs(), builder.getConnectionTimeoutMs(), 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);
                processEvent(event);
            }
        }, builder.getRetryPolicy(), builder.canBeReadOnly());

        listeners = new ListenerContainer<CuratorListener>();
        unhandledErrorListeners = new ListenerContainer<UnhandledErrorListener>();
        backgroundOperations = new DelayQueue<OperationAndData<?>>();
        namespace = new NamespaceImpl(this, builder.getNamespace());
        threadFactory = getThreadFactory(builder);
        maxCloseWaitMs = builder.getMaxCloseWaitMs();
        connectionStateManager = new ConnectionStateManager(this, builder.getThreadFactory());
        compressionProvider = builder.getCompressionProvider();
        aclProvider = builder.getAclProvider();
        state = new AtomicReference<CuratorFrameworkState>(CuratorFrameworkState.LATENT);
        useContainerParentsIfAvailable = builder.useContainerParentsIfAvailable();

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

        failedDeleteManager = new FailedDeleteManager(this);
        namespaceFacadeCache = new NamespaceFacadeCache(this);
    }

3.1 ZookeeperFactory的构建

//1.从builder里拿出ZookeeperFactory
ZookeeperFactory localZookeeperFactory = makeZookeeperFactory(builder.getZookeeperFactory());

//2.builder里的默认ZookeeperFactory
private ZookeeperFactory zookeeperFactory = DEFAULT_ZOOKEEPER_FACTORY;
private static final DefaultZookeeperFactory DEFAULT_ZOOKEEPER_FACTORY = new DefaultZookeeperFactory();

//3.ZookeeperFactory的默认实现类,默认zookeeper工厂
//实际上就是new一个org.apache.zookeeper.ZooKeeper,原生态的Zookeeper。
public class DefaultZookeeperFactory implements ZookeeperFactory
{
    @Override
    public ZooKeeper newZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly) throws Exception
    {
        return new ZooKeeper(connectString, sessionTimeout, watcher, canBeReadOnly);
    }
}

//4.包装一层,加上鉴权信息
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;
            }
        };
    }

3.2 ConnectionStateManager的构建

设置其service为单例ExecutorService。主要用在监控链接状态。

public ConnectionStateManager(CuratorFramework client, ThreadFactory threadFactory)
    {
        this.client = client;
        if ( threadFactory == null )
        {
            threadFactory = ThreadUtils.newThreadFactory("ConnectionStateManager");
        }
        service = Executors.newSingleThreadExecutor(threadFactory);
    }

4.CuratorZookeeperClient定义

在CuratorFrameworkImpl初始化的时候构建

1.初始化,需要新建Watcher

this.client = new CuratorZookeeperClient(localZookeeperFactory, builder.getEnsembleProvider(), builder.getSessionTimeoutMs(), builder.getConnectionTimeoutMs(), 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);
                processEvent(event);//调用本类的方法
            }
        }, builder.getRetryPolicy(), builder.canBeReadOnly());

2.listeners采用函数式编程,此处的监听执行就是在ConnectionState里的process调用的。

private void processEvent(final CuratorEvent curatorEvent)
    {
        if ( curatorEvent.getType() == CuratorEventType.WATCHED )
        {
            validateConnection(curatorEvent.getWatchedEvent().getState());
        }

        listeners.forEach(new Function<CuratorListener, Void>()
        {
            @Override
            public Void apply(CuratorListener listener)
            {
                try
                {
                    TimeTrace trace = client.startTracer("EventListener");
                    listener.eventReceived(CuratorFrameworkImpl.this, curatorEvent);
                    trace.commit();
                }
                catch ( Exception e )
                {
                    logError("Event listener threw exception", e);
                }
                return null;
            }
        });
    } 

3.主要有2个字段ConnectionState连接状态,retryPolicy 重复策略就在如下定义。

    private final ConnectionState                   state;
    private final AtomicReference<RetryPolicy>      retryPolicy = new AtomicReference<RetryPolicy>();

初始化主要做了如下工作,校验重复策略不能为空,校验配置链接地址提供者不能为空,初始化ConnectionState,设置重复策略。

public CuratorZookeeperClient(ZookeeperFactory zookeeperFactory, EnsembleProvider ensembleProvider,
 int sessionTimeoutMs, int connectionTimeoutMs, Watcher watcher, RetryPolicy retryPolicy, boolean canBeReadOnly)
    {
        if ( sessionTimeoutMs < connectionTimeoutMs )
        {
            log.warn(String.format("session timeout [%d] is less than connection timeout [%d]", sessionTimeoutMs, connectionTimeoutMs));
        }

        retryPolicy = Preconditions.checkNotNull(retryPolicy, "retryPolicy cannot be null");
        ensembleProvider = Preconditions.checkNotNull(ensembleProvider, "ensembleProvider cannot be null");

        this.connectionTimeoutMs = connectionTimeoutMs;
        state = new ConnectionState(zookeeperFactory, ensembleProvider, sessionTimeoutMs, connectionTimeoutMs, watcher, tracer, canBeReadOnly);
        setRetryPolicy(retryPolicy);
    }

5.ConnectionState定义

ConnectionState实现了Watcher和Closeable接口。
设置了链接地址的配置策略,session过期时间,链接超时时间,设置日志追踪驱动器(使用的默认的DefaultTracerDriver),
将传递进来的watcher放入parentWatchers中,最后定义HandleHolder。

private final Queue<Watcher> parentWatchers = new ConcurrentLinkedQueue<Watcher>();
ConnectionState(ZookeeperFactory zookeeperFactory, EnsembleProvider ensembleProvider, int sessionTimeoutMs, 
int connectionTimeoutMs, Watcher parentWatcher, AtomicReference<TracerDriver> tracer, boolean canBeReadOnly)
    {
        this.ensembleProvider = ensembleProvider;
        this.sessionTimeoutMs = sessionTimeoutMs;
        this.connectionTimeoutMs = connectionTimeoutMs;
        this.tracer = tracer;
        if ( parentWatcher != null )
        {
            parentWatchers.offer(parentWatcher);
        }

        //这个地方的this就是ConnectionState实现Watcher接口的原因。
        zooKeeper = new HandleHolder(zookeeperFactory, this, ensembleProvider, sessionTimeoutMs, canBeReadOnly);
    }

    //主要用来执行CuratorFrameworkImpl里的监听。
    //第一、根据当前ConnectionState的isConnected与事件的状态,
    //去检查当前的事件的KeeperState,在checkState过程中,
    //若为SyncConnected和ConnectedReadOnly表示为链接状态,其他则为断链状态;
    //同时若过期Expired,会重新链接zookeeper,
    //不过期的会去判断当前链接地址是否发生变化,若发生也会重新链接zookeeper。
    //同时若链接状态与之前的不同再修改状态。(详细的在以后讲去了)
    //第二、将parentWatchers里的所有watcher全部调用一次。
    @Override
    public void process(WatchedEvent event)
    {
        if ( LOG_EVENTS )
        {
            log.debug("ConnectState watcher: " + event);
        }

        if ( event.getType() == Watcher.Event.EventType.None )
        {
            boolean wasConnected = isConnected.get();
            boolean newIsConnected = checkState(event.getState(), wasConnected);
            if ( newIsConnected != wasConnected )
            {
                isConnected.set(newIsConnected);
                connectionStartMs = System.currentTimeMillis();
            }
        }

        for ( Watcher parentWatcher : parentWatchers )
        {
            TimeTrace timeTrace = new TimeTrace("connection-state-parent-process", tracer.get());
            parentWatcher.process(event);
            timeTrace.commit();
        }
    }

private boolean checkState(Event.KeeperState state, boolean wasConnected)
    {
        boolean isConnected = wasConnected;
        boolean checkNewConnectionString = true;
        switch ( state )
        {
        default:
        case Disconnected:
        {
            isConnected = false;
            break;
        }

        case SyncConnected:
        case ConnectedReadOnly:
        {
            isConnected = true;
            break;
        }

        case AuthFailed:
        {
            isConnected = false;
            log.error("Authentication failed");
            break;
        }
        //若过期Expired,会重新链接zookeeper
        case Expired:
        {
            isConnected = false;
            checkNewConnectionString = false;
            handleExpiredSession();
            break;
        }

        case SaslAuthenticated:
        {
            // NOP
            break;
        }
        }

        if ( checkNewConnectionString && zooKeeper.hasNewConnectionString() )
        {
            handleNewConnectionString();
        }

        return isConnected;
    }

6.HandleHolder定义

简单的设置5个字段

HandleHolder(ZookeeperFactory zookeeperFactory, 
Watcher watcher, EnsembleProvider ensembleProvider, 
int sessionTimeout, boolean canBeReadOnly)
    {
        this.zookeeperFactory = zookeeperFactory;
        this.watcher = watcher;
        this.ensembleProvider = ensembleProvider;
        this.sessionTimeout = sessionTimeout;
        this.canBeReadOnly = canBeReadOnly;
    }

总结

  • 主要使用到CuratorFrameworkImpl,CuratorZookeeperClient,ConnectionState,HandleHolder4个类,一步一步往后定义;
  • 同时使用ConnectionStateManager进行链接状态监控;

启动

CuratorFrameworkImpl启动

先校验状态是否为LATENT并设置为STARTED。
启动connectionStateManager。
链接状态管理器中增加一个监听器,用于在链接状态时将client的logAsErrorConnectionErrors设为true。
再启动CuratorZookeeperClient。
executorService定义成2个线程的执行器,1个为监听,1个为后台。并执行后台的循环操作。

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);
                    }
                }
            };

            this.getConnectionStateListenable().addListener(listener);

            client.start();

            executorService = Executors.newFixedThreadPool(2, threadFactory);  // 1 for listeners, 1 for background ops

            executorService.submit(new Callable<Object>()
            {
                @Override
                public Object call() throws Exception
                {
                    backgroundOperationsLoop();
                    return null;
                }
            });
        }
        catch ( Exception e )
        {
            handleBackgroundOperationException(null, e);
        }
    }

ConnectionStateManager启动

启动一个ConnectionStateManager的线程执行者,通过listeners的函数式编程去执行监听状态变化。

   /**
     * Start the manager
     */
    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;
                    }
                }
            );
    }

private void processEvents()
    {
        try
        {
            while ( !Thread.currentThread().isInterrupted() )
            {   //take方法可以阻塞
                final ConnectionState newState = eventQueue.take();

                if ( listeners.size() == 0 )
                {
                    log.warn("There are no ConnectionStateListeners registered.");
                }

                listeners.forEach
                    (
                        new Function<ConnectionStateListener, Void>()
                        {
                            @Override
                            public Void apply(ConnectionStateListener listener)
                            {
                                listener.stateChanged(client, newState);
                                return null;
                            }
                        }
                    );
            }
        }
        catch ( InterruptedException e )
        {
            Thread.currentThread().interrupt();
        }
    }

CuratorZookeeperClient启动

需要校验CuratorZookeeperClient是否已启动,若启动抛异常。
再去启动ConnectionState。

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

        if ( !started.compareAndSet(false, true) )
        {
            IllegalStateException ise = new IllegalStateException("Already started");
            throw ise;
        }

        state.start();
    }

ConnectionState启动

先启动链接地址配置器。
再重设。
在重设中,原子性的增加实例次数1次;
同时将链接状态设为false,
再去启动HandleHolder,
同时最重要一步zooKeeper.getZooKeeper()初始化原生态的链接;

void start() throws Exception
    {
        log.debug("Starting");
        ensembleProvider.start();
        reset();
    }

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

        instanceIndex.incrementAndGet();

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

HandleHolder启动

可以看出借用内部接口Helper来完成操作的。
Helper接口有2方法,一个获取原生的zookeeper,一个是获取链接地址路径。

private interface Helper
    {
        ZooKeeper getZooKeeper() throws Exception;

        String getConnectionString();
    }

重点还是在closeAndReset方法上。
主要还是在helper上的初始化,
当第一次调用getZooKeeper 时用synchronized 包裹,并会对链接地址和zookeeper定义,同时再次定义helper对象,并将此次定义好的两个值作为返回值去实现此前的2个方法。此刻以后每次调用getZooKeeper 时均从子helper里的方法。避免同时有客户端new zookeeper。

void closeAndReset() throws Exception
    {
        internalClose();
        // first helper is synchronized when getZooKeeper is called. Subsequent calls
        // are not synchronized.
        helper = new Helper()
        {
            private volatile ZooKeeper zooKeeperHandle = null;
            private volatile String connectionString = null;

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

                    helper = new Helper()
                    {
                        @Override
                        public ZooKeeper getZooKeeper() throws Exception
                        {
                            return zooKeeperHandle;
                        }

                        @Override
                        public String getConnectionString()
                        {
                            return connectionString;
                        }
                    };

                    return zooKeeperHandle;
                }
            }

            @Override
            public String getConnectionString()
            {
                return connectionString;
            }
        };
    }

ZooKeeper getZooKeeper() throws Exception
    {
        return (helper != null) ? helper.getZooKeeper() : null;
    }

猜你喜欢

转载自blog.csdn.net/zjw10wei321/article/details/50384445