Dubbo-服务注册中心之AbstractRegistryFactory等源码
在上文中介绍了基础类AbstractRegistry类的解释,在本篇中将继续介绍该包下的其他类。
FailbackRegistry
该类继承了AbstractRegistry,AbstractRegistry中的注册订阅等方法,实际上就是一些内存缓存的变化,而真正的注册订阅的实现逻辑在FailbackRegistry实现,并且FailbackRegistry提供了失败重试的机制。
初始化
// Scheduled executor service // 定时任务执行器 private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboRegistryFailedRetryTimer", true)); // Timer for failure retry, regular check if there is a request for failure, and if there is, an unlimited retry // 失败重试定时器,定时去检查是否有请求失败的,如有,无限次重试。 private final ScheduledFuture<?> retryFuture; // 注册失败的URL集合 private final Set<URL> failedRegistered = new ConcurrentHashSet<URL>(); // 取消注册失败的URL集合 private final Set<URL> failedUnregistered = new ConcurrentHashSet<URL>(); // 订阅失败的监听器集合 private final ConcurrentMap<URL, Set<NotifyListener>> failedSubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>(); // 取消订阅失败的监听器集合 private final ConcurrentMap<URL, Set<NotifyListener>> failedUnsubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>(); // 通知失败的URL集合 private final ConcurrentMap<URL, Map<NotifyListener, List<URL>>> failedNotified = new ConcurrentHashMap<URL, Map<NotifyListener, List<URL>>>(); /** * The time in milliseconds the retryExecutor will wait */ // 重试频率 private final int retryPeriod;
构造函数
public FailbackRegistry(URL url) { super(url); // 从url中读取重试频率,如果为空,则默认5000ms this.retryPeriod = url.getParameter(Constants.REGISTRY_RETRY_PERIOD_KEY, Constants.DEFAULT_REGISTRY_RETRY_PERIOD); // 创建失败重试定时器 this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() { @Override public void run() { // Check and connect to the registry try { //重试 retry(); } catch (Throwable t) { // Defensive fault tolerance logger.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t); } } }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS); }
构造函数主要是创建了失败重试的定时器,重试频率从URL取,如果没有设置,则默认为5000ms。
在该类中对注册、取消注册、订阅、取消订阅进行了重写操作,代码逻辑相对简单。
@Override public void register(URL url) { super.register(url); //首先从失败的缓存中删除该url failedRegistered.remove(url); failedUnregistered.remove(url); try { // Sending a registration request to the server side // 向注册中心发送一个注册请求 doRegister(url); } catch (Exception e) { Throwable t = e; // If the startup detection is opened, the Exception is thrown directly. // 如果开启了启动时检测,则直接抛出异常 boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) && url.getParameter(Constants.CHECK_KEY, true) && !Constants.CONSUMER_PROTOCOL.equals(url.getProtocol()); boolean skipFailback = t instanceof SkipFailbackWrapperException; if (check || skipFailback) { if (skipFailback) { t = t.getCause(); } throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t); } else { logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t); } // Record a failed registration request to a failed list, retry regularly // 把这个注册失败的url放入缓存,并且定时重试。 failedRegistered.add(url); } }
在注册中它会失败的注册缓存和失败的未注册缓存集合中移除该URL,然后向注册中心执行注册。
AbstractRegistryFactory
该类实现了RegistryFactory接口,抽象了createRegistry方法,它实现了Registry的容器。
初始化
private static final ReentrantLock LOCK = new ReentrantLock(); // Registry Collection Map<RegistryAddress, Registry> // Registry 集合 private static final Map<String, Registry> REGISTRIES = new ConcurrentHashMap<String, Registry>();
销毁所有的Registry对象,并清理缓存数据
public static Collection<Registry> getRegistries() { return Collections.unmodifiableCollection(REGISTRIES.values()); } public static void destroyAll() { if (LOGGER.isInfoEnabled()) { LOGGER.info("Close all registries " + getRegistries()); } // Lock up the registry shutdown process // 获得锁 LOCK.lock(); try { for (Registry registry : getRegistries()) { try { // 销毁 registry.destroy(); } catch (Throwable e) { LOGGER.error(e.getMessage(), e); } } // 清空缓存 REGISTRIES.clear(); } finally { // Release the lock // 释放锁 LOCK.unlock(); } }
该方法是实现了Registry接口的方法,这里最要注意的是createRegistry,因为AbstractRegistryFfactory本身就是抽象类,而createRegistry也是抽象方法,为了让子类只要关注该方法,比如说redis实现的注册中心和zookeeper实现的注册中心创建方式肯定不同,而他们相同的一些操作都已经在AbstractRegistryFactory中实现,所以只要关注且实现该抽象方法即可。
@Override public Registry getRegistry(URL url) { // 修改url url = url.setPath(RegistryService.class.getName()) .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName()) .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY); // 计算key值 String key = url.toServiceString(); // Lock the registry access process to ensure a single instance of the registry // 获得锁 LOCK.lock(); try { Registry registry = REGISTRIES.get(key); if (registry != null) { return registry; } // 创建Registry对象 registry = createRegistry(url); if (registry == null) { throw new IllegalStateException("Can not create registry " + url); } // 添加到缓存。 REGISTRIES.put(key, registry); return registry; } finally { // Release the lock // 释放锁 LOCK.unlock(); } }
相关推荐
ATenhong 2020-10-15
supperme 2020-09-08
doctorvian 2020-08-02
aNian 2020-08-01
kongjunlongaa 2020-06-29
Fightingxr 2020-06-26
whileinsist 2020-06-24
doctorvian 2020-06-16
XuNeely 2020-06-16
wangyangsoftware 2020-06-16
大步流星 2020-06-16
aNian 2020-06-16
gaoyongstone 2020-06-16
MartellJenkins 2020-06-11
范群松 2020-06-11
Fightingxr 2020-06-08
XuNeely 2020-06-07
大步流星 2020-06-05