FailbackRegistry extends AbstractRegistry { @Override public void subscribe(URL url, NotifyListener listener) { super.subscribe(url, listener); removeFailedSubscribed(url, listener); try { doSubscribe(url, listener); } catch (Exception e) { Throwable t = e; List<URL> urls = getCacheUrls(url); if (CollectionUtils.isNotEmpty(urls)) { notify(url, listener, urls); logger.error("Failed to subscribe " + url + ", Using cached list: " + urls + " from cache file: " + getUrl().getParameter(FILE_KEY, System.getProperty("user.home") + "/dubbo-registry-" + url.getHost() + ".cache") + ", cause: " + t.getMessage(), t); } else { boolean check = getUrl().getParameter(Constants.CHECK_KEY, true) && url.getParameter(Constants.CHECK_KEY, true); boolean skipFailback = t instanceof SkipFailbackWrapperException; if (check || skipFailback) { if (skipFailback) { t = t.getCause(); } throw new IllegalStateException("Failed to subscribe " + url + ", cause: " + t.getMessage(), t); } else { logger.error("Failed to subscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t); } } addFailedSubscribed(url, listener); } } FailbackRegistry(URL url); void removeFailedRegisteredTask(URL url); void removeFailedUnregisteredTask(URL url); void removeFailedSubscribedTask(URL url, NotifyListener listener); void removeFailedUnsubscribedTask(URL url, NotifyListener listener); @Override void register(URL url); @Override void reExportRegister(URL url); @Override void unregister(URL url); @Override void reExportUnregister(URL url); @Override void subscribe(URL url, NotifyListener listener); @Override void unsubscribe(URL url, NotifyListener listener); @Override void destroy(); abstract void doRegister(URL url); abstract void doUnregister(URL url); abstract void doSubscribe(URL url, NotifyListener listener); abstract void doUnsubscribe(URL url, NotifyListener listener);  }
@Test public void testDoRetry_register() throws Exception { final AtomicReference<Boolean> notified = new AtomicReference<Boolean>(false); final CountDownLatch latch = new CountDownLatch(1); NotifyListener listner = new NotifyListener() { @Override public void notify(List<URL> urls) { notified.set(Boolean.TRUE); } }; registry = new MockRegistry(registryUrl, latch); registry.setBad(true); registry.subscribe(serviceUrl.setProtocol(CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); assertEquals(false, notified.get()); assertEquals(1, latch.getCount()); registry.setBad(false); for (int i = 0; i < trytimes; i++) { System.out.println("failback registry retry ,times:" + i); if (latch.getCount() == 0) break; Thread.sleep(sleeptime); } assertEquals(0, latch.getCount()); assertEquals(true, notified.get()); }