Dubbo-聊聊注册中心的设计( 七 )

重试机制关于重试机制,Dubbo将重试机制放在了FailbackRegistry类中,FailbackRegistry 设计思想,重写了 AbstractRegistry 中 register()/unregister()、subscribe()/unsubscribe() 以及 notify() 这五个核心方法,结合时间轮,实现失败重试机制 。此外,还添加了四个未实现的抽象模板方法,由其继承者去实现,这里也就是典型的模板类的设计 。
核心字段介绍    //注册失败的URL Key是注册失败的 URL,Value 是对应的重试任务    private final ConcurrentMap<URL, FailedRegisteredTask> failedRegistered = new ConcurrentHashMap<URL, FailedRegisteredTask>();    //取消注册失败URL    private final ConcurrentMap<URL, FailedUnregisteredTask> failedUnregistered = new ConcurrentHashMap<URL, FailedUnregisteredTask>();    //订阅失败的URL    private final ConcurrentMap<Holder, FailedSubscribedTask> failedSubscribed = new ConcurrentHashMap<Holder, FailedSubscribedTask>();    //取消订阅失败的URL    private final ConcurrentMap<Holder, FailedUnsubscribedTask> failedUnsubscribed = new ConcurrentHashMap<Holder, FailedUnsubscribedTask>();    //重试的时间间隔    private final int retryPeriod;    //用于定时执行失败的时间轮    private final HashedWheelTimer retryTimer;构造方法首先会调用父类的构造方法完成本地缓存相关的初始化操作,然后根据传入URL参数中获取重试操作的时间间隔来初始化 retryPeriod 字段,最后初始化 HashedWheelTimer时间轮 。
    public FailbackRegistry(URL url) {        //调用        super(url);        this.retryPeriod = url.getParameter(REGISTRY_RETRY_PERIOD_KEY, DEFAULT_REGISTRY_RETRY_PERIOD);        retryTimer = new HashedWheelTimer(new NamedThreadFactory("DubboRegistryRetryTimer", true), retryPeriod, TimeUnit.MILLISECONDS, 128);    }核心方法registerregister方法重写了父类的注册方法,首先调用父类的register将url加入对应的容器,然后从failedRegistered 和failedUnregistered 两个容器中移除失败URL,然后执行doRegister方法,doRegister是抽象方法,具体的实现交给其继承者,如果注册失败抛出异常,会将URL加入failedRegistered 容器中 。
    @Override    public void register(URL url) {        if (!acceptable(url)) {            logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type.");            return;        }        //执行父类的方法加入到容器中        super.register(url);        //移除注册失败        removeFailedRegistered(url);        //移除取消注册失败        removeFailedUnregistered(url);        try {            //抽象方法交给具体子类去实现            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)                    && !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);            }            //注册发生异常将注册失败放入到注册失败的容器中            addFailedRegistered(url);        }    }

经验总结扩展阅读