io.github.icodegarden.commons.zookeeper.registry.NamesWatchedZooKeeperInstanceDiscovery Maven / Gradle / Ivy
package io.github.icodegarden.commons.zookeeper.registry;
import java.io.IOException;
import java.util.List;
import org.apache.zookeeper.AddWatchMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.icodegarden.commons.lang.NamesCachedObjectReader;
import io.github.icodegarden.commons.zookeeper.NewZooKeeperListener;
import io.github.icodegarden.commons.zookeeper.ZooKeeperHolder;
import io.github.icodegarden.commons.zookeeper.exception.ExceedExpectedZooKeeperException;
import io.github.icodegarden.commons.zookeeper.exception.ZooKeeperException;
/**
* 只关注给定的serviceNames
* NamesCached + watch实时变更
*
* @author Fangfang.Xu
*
*/
public class NamesWatchedZooKeeperInstanceDiscovery
implements ZooKeeperInstanceDiscovery, NewZooKeeperListener, Watcher {
private static final Logger log = LoggerFactory.getLogger(NamesWatchedZooKeeperInstanceDiscovery.class);
private ZooKeeperHolder zooKeeperHolder;
private String root;
private final List serviceNames;
private final ZooKeeperInstanceDiscovery extends ZooKeeperRegisteredInstance> delegator;
private final NamesCachedObjectReader namesCachedObjectReader;
/**
*
* @param zooKeeperHolder
* @param root
* @param serviceNames 需要watch的serviceNames
* @param cacheRefreshIntervalMillis
* @throws IllegalArgumentException
*/
public NamesWatchedZooKeeperInstanceDiscovery(
ZooKeeperInstanceDiscovery extends ZooKeeperRegisteredInstance> delegator,
ZooKeeperHolder zooKeeperHolder, String root, List serviceNames, long cacheRefreshIntervalMillis)
throws IllegalArgumentException {
if (delegator == null) {
throw new IllegalArgumentException("param delegator must not null");
}
if (zooKeeperHolder == null) {
throw new IllegalArgumentException("param zooKeeperHolder must not null");
}
if (root == null || root.isEmpty()) {
throw new IllegalArgumentException("param root must not empty");
}
if (!root.startsWith("/")) {
throw new IllegalArgumentException("param root must start with /");
}
if (root.endsWith("/")) {
throw new IllegalArgumentException("param root must not end with /");
}
if (serviceNames == null || serviceNames.isEmpty()) {
throw new IllegalArgumentException("serviceNames must not empty");
}
this.delegator = delegator;
this.zooKeeperHolder = zooKeeperHolder;
this.root = root;
this.serviceNames = serviceNames;
namesCachedObjectReader = new NamesCachedObjectReader(serviceNames, delegator, cacheRefreshIntervalMillis);
addWatchers();
}
@Override
public void onNewZooKeeper() {
/**
* 当new zk创建后需要重新add watcher
*/
addWatchers();
}
private void addWatchers() throws ZooKeeperException {
for (String serviceName : serviceNames) {
String path = ServiceNamePath.buildServiceNamePath(root, serviceName);
try {
// 递归他的子节点
zooKeeperHolder.getConnectedZK().addWatch(path, this, AddWatchMode.PERSISTENT_RECURSIVE);
} catch (KeeperException | InterruptedException e) {
throw new ExceedExpectedZooKeeperException(
String.format("ex on addWatch,serviceName [%s], path [%s]", serviceName, path), e);
}
}
}
private void removeWatchers() throws ZooKeeperException {
for (String serviceName : serviceNames) {
String path = ServiceNamePath.buildServiceNamePath(root, serviceName);
try {
zooKeeperHolder.getConnectedZK().removeWatches(path, this, WatcherType.Any,
true/* true时,当connection不可用时可以只移除本地 */);
} catch (KeeperException.NoWatcherException e) {
/**
* 没有该watcher,忽略
*/
} catch (KeeperException | InterruptedException e) {
throw new ExceedExpectedZooKeeperException(
String.format("ex on removeWatch,serviceName [%s], path [%s]", serviceName, path), e);
}
}
}
@Override
public List listNamedObjects(String serviceName) throws ZooKeeperException {
return (List) namesCachedObjectReader.listNamedObjects(serviceName);
}
@Override
public ZooKeeperRegisteredInstance parseInstance(Object data) {
return delegator.parseInstance(data);
}
/**
* path: /beecomb/worker/instances/10.33.211.12:10000-0000000115
*/
@Override
public void process(WatchedEvent event) {
switch (event.getType()) {
case NodeCreated: {
String znode = event.getPath();
if (log.isInfoEnabled()) {
log.info("watched znode was created, a instance was registered, znode:{}", znode);
}
ZooKeeperRegisteredInstance registeredInstance = parseInstance(znode);
if (registeredInstance != null) {
namesCachedObjectReader.addObject(registeredInstance);
} else {
if (log.isWarnEnabled()) {
log.warn("znode parseInstance is null on znode created");
}
}
}
break;
case NodeDeleted: {
String znode = event.getPath();
if (log.isInfoEnabled()) {
log.info("watched znode was deleted, a instance was deregistered, znode:{}", znode);
}
ZooKeeperRegisteredInstance registeredInstance = parseInstance(znode);
if (registeredInstance != null) {
namesCachedObjectReader.removeObject(registeredInstance);
} else {
if (log.isWarnEnabled()) {
log.warn("znode parseInstance is null on znode deleted");
}
}
}
break;
default:
break;
}
}
@Override
public void close() throws IOException {
try {
removeWatchers();
} catch (Exception e) {
log.error("WARN ex on removeWatchers when close", e);
}
namesCachedObjectReader.close();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy