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