![JAR search and dependency download from the Maven repository](/logo.png)
com.github.ltsopensource.core.registry.FailbackRegistry Maven / Gradle / Ivy
package com.github.ltsopensource.core.registry;
import com.github.ltsopensource.core.AppContext;
import com.github.ltsopensource.core.cluster.Node;
import com.github.ltsopensource.core.commons.concurrent.ConcurrentHashSet;
import com.github.ltsopensource.core.commons.utils.Callable;
import com.github.ltsopensource.core.constant.Constants;
import com.github.ltsopensource.core.constant.ExtConfig;
import com.github.ltsopensource.core.factory.NamedThreadFactory;
import com.github.ltsopensource.core.support.NodeShutdownHook;
import java.util.*;
import java.util.concurrent.*;
/**
* @author Robert HG ([email protected]) on 5/17/15.
*/
public abstract class FailbackRegistry extends AbstractRegistry {
// 定时任务执行器
private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1,
new NamedThreadFactory("LTSRegistryFailedRetryTimer", true));
// 失败重试定时器,定时检查是否有请求失败,如有,无限次重试
private ScheduledFuture> retryFuture;
// 注册失败的定时重试
private final Set failedRegistered = new ConcurrentHashSet();
private final Set failedUnRegistered = new ConcurrentHashSet();
private final ConcurrentMap> failedSubscribed = new ConcurrentHashMap>();
private final ConcurrentMap> failedUnsubscribed = new ConcurrentHashMap>();
private final ConcurrentMap>>> failedNotified = new ConcurrentHashMap>>>();
public FailbackRegistry(AppContext appContext) {
super(appContext);
int retryPeriod = appContext.getConfig().getParameter(ExtConfig.REGISTRY_RETRY_PERIOD_KEY, Constants.DEFAULT_REGISTRY_RETRY_PERIOD);
this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {
public void run() {
// 检测并连接注册中心
try {
retry();
} catch (Throwable t) { // 防御性容错
LOGGER.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t);
}
}
}, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);
NodeShutdownHook.registerHook(appContext, this.getClass().getName(), new Callable() {
@Override
public void call() throws Exception {
retryFuture.cancel(true);
retryExecutor.shutdownNow();
destroy();
}
});
}
@Override
public void register(Node node) {
try {
super.register(node);
failedRegistered.clear();
doRegister(node);
} catch (Exception e) {
// 将失败的注册请求记录到失败列表,定时重试
failedRegistered.add(node);
}
}
@Override
public void unregister(Node node) {
try {
super.unregister(node);
failedUnRegistered.clear();
doUnRegister(node);
} catch (Exception e) {
// 将失败的取消注册请求记录到失败列表,定时重试
failedUnRegistered.add(node);
}
}
@Override
public void subscribe(Node node, NotifyListener listener) {
try {
super.subscribe(node, listener);
removeFailedSubscribed(node, listener);
doSubscribe(node, listener);
} catch (Exception e) {
addFailedSubscribed(node, listener);
}
}
@Override
public void unsubscribe(Node node, NotifyListener listener) {
try {
super.unsubscribe(node, listener);
removeFailedSubscribed(node, listener);
doUnsubscribe(node, listener);
} catch (Exception e) {
addFailedUnsubscribed(node, listener);
}
}
protected void addFailedUnsubscribed(Node node, NotifyListener listener) {
// 将失败的取消订阅请求记录到失败列表,定时重试
Set listeners = failedUnsubscribed.get(node);
if (listeners == null) {
failedUnsubscribed.putIfAbsent(node, new ConcurrentHashSet());
listeners = failedUnsubscribed.get(node);
}
listeners.add(listener);
}
@Override
protected void notify(NotifyEvent event, List nodes, NotifyListener listener) {
try {
super.notify(event, nodes, listener);
} catch (Exception e) {
// 将失败的通知请求记录到失败列表,定时重试
Map>> listeners = failedNotified.get(getNode());
if (listeners == null) {
failedNotified.putIfAbsent(getNode(), new ConcurrentHashMap>>());
listeners = failedNotified.get(getNode());
}
listeners.put(listener, new NotifyPair>(event, nodes));
LOGGER.error("Failed to notify, waiting for retry, cause: " + e.getMessage(), e);
}
}
@Override
public void destroy() {
super.destroy();
try {
retryFuture.cancel(true);
} catch (Throwable t) {
LOGGER.warn(t.getMessage(), t);
}
}
@Override
protected void recover() throws Exception {
// register
Set recoverRegistered = new HashSet(getRegistered());
if (!recoverRegistered.isEmpty()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Recover register node " + recoverRegistered);
}
for (Node node : recoverRegistered) {
failedRegistered.add(node);
}
}
// subscribe
Map> recoverSubscribed = new HashMap>(getSubscribed());
if (!recoverSubscribed.isEmpty()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Recover subscribe node " + recoverSubscribed.keySet());
}
for (Map.Entry> entry : recoverSubscribed.entrySet()) {
Node node = entry.getKey();
for (NotifyListener listener : entry.getValue()) {
addFailedSubscribed(node, listener);
}
}
}
}
private void removeFailedSubscribed(Node node, NotifyListener listener) {
Set listeners = failedSubscribed.get(node);
if (listeners != null) {
listeners.remove(listener);
}
listeners = failedUnsubscribed.get(node);
if (listeners != null) {
listeners.remove(listener);
}
Map>> notified = failedNotified.get(node);
if (notified != null) {
notified.remove(listener);
}
}
private void addFailedSubscribed(Node node, NotifyListener listener) {
Set listeners = failedSubscribed.get(node);
if (listeners == null) {
failedSubscribed.putIfAbsent(node, new ConcurrentHashSet());
listeners = failedSubscribed.get(node);
}
listeners.add(listener);
}
protected void retry() {
if (!failedRegistered.isEmpty()) {
Set failed = new HashSet(failedRegistered);
if (failed.size() > 0) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Retry register {}", failed);
}
try {
for (Node node : failed) {
doRegister(node);
failedRegistered.remove(node);
}
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry register " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
if (!failedUnRegistered.isEmpty()) {
Set failed = new HashSet(failedUnRegistered);
if (failed.size() > 0) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Retry unregister {}", failed);
}
try {
for (Node node : failed) {
doUnRegister(node);
failedUnRegistered.remove(node);
}
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry unregister " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
if (!failedSubscribed.isEmpty()) {
Map> failed = new HashMap>(failedSubscribed);
for (Map.Entry> entry : new HashMap>(failed).entrySet()) {
if (entry.getValue() == null || entry.getValue().size() == 0) {
failed.remove(entry.getKey());
}
}
if (failed.size() > 0) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Retry subscribe " + failed);
}
try {
for (Map.Entry> entry : failed.entrySet()) {
Node node = entry.getKey();
Set listeners = entry.getValue();
for (NotifyListener listener : listeners) {
try {
doSubscribe(node, listener);
listeners.remove(listener);
failedSubscribed.remove(entry.getKey());
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry subscribe " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry subscribe " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
if (!failedUnsubscribed.isEmpty()) {
Map> failed = new HashMap>(failedUnsubscribed);
for (Map.Entry> entry : new HashMap>(failed).entrySet()) {
if (entry.getValue() == null || entry.getValue().size() == 0) {
failed.remove(entry.getKey());
}
}
if (failed.size() > 0) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Retry unsubscribe " + failed);
}
try {
for (Map.Entry> entry : failed.entrySet()) {
Node node = entry.getKey();
Set listeners = entry.getValue();
for (NotifyListener listener : listeners) {
try {
doUnsubscribe(node, listener);
listeners.remove(listener);
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry unsubscribe " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry unsubscribe " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
if (!failedNotified.isEmpty()) {
Map>>> failed = new HashMap>>>(failedNotified);
for (Map.Entry>>> entry : new HashMap>>>(failed).entrySet()) {
if (entry.getValue() == null || entry.getValue().size() == 0) {
failed.remove(entry.getKey());
}
}
if (failed.size() > 0) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Retry notify " + failed);
}
try {
for (Map>> values : failed.values()) {
for (Map.Entry>> entry : values.entrySet()) {
try {
NotifyListener listener = entry.getKey();
NotifyPair> notifyPair = entry.getValue();
listener.notify(notifyPair.event, notifyPair.nodes);
values.remove(listener);
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry notify " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
} catch (Throwable t) { // 忽略所有异常,等待下次重试
LOGGER.warn("Failed to retry notify " + failed + ", waiting for again, cause: " + t.getMessage(), t);
}
}
}
}
private class NotifyPair {
T1 event;
T2 nodes;
public NotifyPair(T1 event, T2 nodes) {
this.event = event;
this.nodes = nodes;
}
}
protected abstract void doRegister(Node node);
protected abstract void doUnRegister(Node node);
protected abstract void doSubscribe(Node node, NotifyListener listener);
protected abstract void doUnsubscribe(Node node, NotifyListener listener);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy