/* * Copyright 1999-2101 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.dubbo.registry.support; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.junit.Before; import org.junit.Test; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.utils.CollectionUtils; import com.alibaba.dubbo.registry.NotifyListener; /** * * @author liuchao */ public class FailbackRegistryTest { MockRegistry registry; static String service; static URL serviceUrl; static URL registryUrl; private int FAILED_PERIOD = 200; private int sleeptime = 100; private int trytimes = 5; /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { service = "com.alibaba.dubbo.test.DemoService"; serviceUrl = URL.valueOf("remote://127.0.0.1/demoservice?method=get"); registryUrl = URL.valueOf("http://1.2.3.4:9090/registry?check=false&file=N/A").addParameter(Constants.REGISTRY_RETRY_PERIOD_KEY,String.valueOf(FAILED_PERIOD)); } /** * Test method for * {@link com.alibaba.dubbo.registry.internal.FailbackRegistry#doRetry()}. * * @throws Exception */ @Test public void testDoRetry() throws Exception { final AtomicReference<Boolean> notified = new AtomicReference<Boolean>(false); final CountDownLatch latch = new CountDownLatch(3);//全部共调用3次。成功才会减1. subscribe register的失败尝试不会在做了 NotifyListener listner = new NotifyListener() { public void notify(List<URL> urls) { notified.set(Boolean.TRUE); } }; registry = new MockRegistry(registryUrl, latch); registry.setBad(true); registry.register(serviceUrl); registry.unregister(serviceUrl); registry.subscribe(serviceUrl.setProtocol(Constants.CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); registry.unsubscribe(serviceUrl.setProtocol(Constants.CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); //失败的情况不能调用到listener. assertEquals(false, notified.get()); assertEquals(3, latch.getCount()); registry.setBad(false); for (int i = 0; i < trytimes; i++) { System.out.println("failback registry retry ,times:" + i); //System.out.println(latch.getCount()); if (latch.getCount() == 0) break; Thread.sleep(sleeptime); } // Thread.sleep(100000);//for debug assertEquals(0, latch.getCount()); //unsubscribe时会清除failedsubcribe对应key assertEquals(false, notified.get()); } @Test public void testDoRetry_subscribe() throws Exception { final CountDownLatch latch = new CountDownLatch(1);//全部共调用4次。成功才会减1. subscribe的失败尝试不会在做了 registry = new MockRegistry(registryUrl, latch); registry.setBad(true); registry.register(serviceUrl); 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()); } @Test public void testDoRetry_register() throws Exception { final AtomicReference<Boolean> notified = new AtomicReference<Boolean>(false); final CountDownLatch latch = new CountDownLatch(1);//全部共调用4次。成功才会减1. subscribe的失败尝试不会在做了 NotifyListener listner = new NotifyListener() { public void notify(List<URL> urls) { notified.set(Boolean.TRUE); } }; registry = new MockRegistry(registryUrl, latch); registry.setBad(true); registry.subscribe(serviceUrl.setProtocol(Constants.CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); //失败的情况不能调用到listener. 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); //System.out.println(latch.getCount()); if (latch.getCount() == 0) break; Thread.sleep(sleeptime); } // Thread.sleep(100000); assertEquals(0, latch.getCount()); //unsubscribe时会清除failedsubcribe对应key assertEquals(true, notified.get()); } @Test public void testDoRetry_nofify() throws Exception { //初始值0 final AtomicInteger count = new AtomicInteger(0); NotifyListener listner = new NotifyListener() { public void notify(List<URL> urls) { count.incrementAndGet(); //第一次抛出异常,看后面是否会再次调用到incrementAndGet if(count.get() == 1l ){ throw new RuntimeException("test exception please ignore"); } } }; registry = new MockRegistry(registryUrl, new CountDownLatch(0)); registry.subscribe(serviceUrl.setProtocol(Constants.CONSUMER_PROTOCOL).addParameters(CollectionUtils.toStringMap("check", "false")), listner); assertEquals(1, count.get()); //确保subscribe调用完成后刚调用过一次count.incrementAndGet //等定时器. for (int i = 0; i < trytimes; i++) { System.out.println("failback notify retry ,times:" + i); if (count.get() == 2) break; Thread.sleep(sleeptime); } assertEquals(2, count.get()); } private static class MockRegistry extends FailbackRegistry { CountDownLatch latch; /** * @param url */ public MockRegistry(URL url, CountDownLatch latch) { super(url); this.latch = latch; } private boolean bad = false; /** * @param bad the bad to set */ public void setBad(boolean bad) { this.bad = bad; } @Override protected void doRegister(URL url) { if (bad) { throw new RuntimeException("can not invoke!"); } //System.out.println("do doRegister"); latch.countDown(); } @Override protected void doUnregister(URL url) { if (bad) { throw new RuntimeException("can not invoke!"); } //System.out.println("do doUnregister"); latch.countDown(); } @Override protected void doSubscribe(URL url, NotifyListener listener) { if (bad) { throw new RuntimeException("can not invoke!"); } //System.out.println("do doSubscribe"); super.notify(url, listener, Arrays.asList(new URL[] { serviceUrl })); latch.countDown(); } @Override protected void doUnsubscribe(URL url, NotifyListener listener) { if (bad) { throw new RuntimeException("can not invoke!"); } //System.out.println("do doUnsubscribe"); latch.countDown(); } @Override protected void retry() { super.retry(); if (bad) { throw new RuntimeException("can not invoke!"); } //System.out.println("do retry"); latch.countDown(); } public boolean isAvailable() { return true; } } }