@SuppressWarnings("unchecked") @Test public void testRpcException() { Logger logger = EasyMock.createMock(Logger.class); RpcContext.getContext().setRemoteAddress("127.0.0.1", 1234); RpcException exception = new RpcException("TestRpcException"); logger.error( EasyMock.eq( "Got unchecked and undeclared exception which called by 127.0.0.1. service: " + DemoService.class.getName() + ", method: sayHello, exception: " + RpcException.class.getName() + ": TestRpcException"), EasyMock.eq(exception)); ExceptionFilter exceptionFilter = new ExceptionFilter(logger); RpcInvocation invocation = new RpcInvocation("sayHello", new Class<?>[] {String.class}, new Object[] {"world"}); Invoker<DemoService> invoker = EasyMock.createMock(Invoker.class); EasyMock.expect(invoker.getInterface()).andReturn(DemoService.class); EasyMock.expect(invoker.invoke(EasyMock.eq(invocation))).andThrow(exception); EasyMock.replay(logger, invoker); try { exceptionFilter.invoke(invoker, invocation); } catch (RpcException e) { assertEquals("TestRpcException", e.getMessage()); } EasyMock.verify(logger, invoker); RpcContext.removeContext(); }
/** Empty notify cause forbidden, non-empty notify cancels forbidden state */ @Test public void testEmptyNotifyCauseForbidden() { RegistryDirectory registryDirectory = getRegistryDirectory(); List invokers = null; List<URL> serviceUrls = new ArrayList<URL>(); registryDirectory.notify(serviceUrls); RpcInvocation inv = new RpcInvocation(); try { invokers = registryDirectory.list(inv); } catch (RpcException e) { Assert.assertEquals(RpcException.FORBIDDEN_EXCEPTION, e.getCode()); Assert.assertEquals(false, registryDirectory.isAvailable()); } serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1")); serviceUrls.add(SERVICEURL2.addParameter("methods", "getXXX1,getXXX2")); serviceUrls.add(SERVICEURL3.addParameter("methods", "getXXX1,getXXX2,getXXX3")); registryDirectory.notify(serviceUrls); inv.setMethodName("getXXX2"); invokers = registryDirectory.list(inv); Assert.assertEquals(true, registryDirectory.isAvailable()); Assert.assertEquals(2, invokers.size()); }
public void doSubscribe(final URL url, final NotifyListener listener) { String service = RedisRegistryUtil.toServicePath(url, root); RedisRegistryNotifier notifier = notifiers.get(service); if (notifier == null) { RedisRegistryNotifier newNotifier = new RedisRegistryNotifier(service, this); notifiers.putIfAbsent(service, newNotifier); notifier = notifiers.get(service); if (notifier == newNotifier) { notifier.start(); } } boolean success = false; RpcException exception = null; for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { if (service.endsWith(Constants.ANY_VALUE)) { admin = true; Set<String> keys = jedis.keys(service); if (keys != null && keys.size() > 0) { Map<String, Set<String>> serviceKeys = RedisRegistryUtil.getServiceKeys(keys, root); for (Set<String> sk : serviceKeys.values()) { doNotify(jedis, sk, url, Arrays.asList(listener)); } } } else { doNotify( jedis, jedis.keys(service + Constants.PATH_SEPARATOR + Constants.ANY_VALUE), url, Arrays.asList(listener)); } success = true; break; // 只需读一个服务器的数据 } finally { jedisPool.returnResource(jedis); } } catch (Throwable t) { // 尝试下一个服务器 exception = new RpcException( "Failed to subscribe service from redis registry. registry: " + entry.getKey() + ", service: " + url + ", cause: " + t.getMessage(), t); } } if (exception != null) { if (success) { logger.warn(exception.getMessage(), exception); } else { throw exception; } } }
protected RpcException getRpcException( Class<?> type, URL url, Invocation invocation, Throwable e) { RpcException re = new RpcException( "Failed to invoke remote service: " + type + ", method: " + invocation.getMethodName() + ", cause: " + e.getMessage(), e); re.setCode(getErrorCode(e)); return re; }
public void doRegister(URL url) { String key = RedisRegistryUtil.toCategoryPath(url, root); String value = url.toFullString(); String expire = String.valueOf(System.currentTimeMillis() + expirePeriod); boolean success = false; RpcException exception = null; for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { jedis.hset(key, value, expire); jedis.publish(key, Constants.REGISTER); success = true; if (!replicate) { break; // 如果服务器端已同步数据,只需写入单台机器 } } finally { jedisPool.returnResource(jedis); } } catch (Throwable t) { exception = new RpcException( "Failed to register service to redis registry. registry: " + entry.getKey() + ", service: " + url + ", cause: " + t.getMessage(), t); } } if (exception != null) { if (success) { logger.warn(exception.getMessage(), exception); } else { throw exception; } } }
// forbid private void testforbid(RegistryDirectory registryDirectory) { invocation = new RpcInvocation(); List<URL> serviceUrls = new ArrayList<URL>(); serviceUrls.add( new URL( Constants.EMPTY_PROTOCOL, Constants.ANYHOST_VALUE, 0, service, Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY)); registryDirectory.notify(serviceUrls); Assert.assertEquals( "invokers size=0 ,then the registry directory is not available", false, registryDirectory.isAvailable()); try { registryDirectory.list(invocation); fail("forbid must throw RpcException"); } catch (RpcException e) { Assert.assertEquals(RpcException.FORBIDDEN_EXCEPTION, e.getCode()); } }
private Result wrapBreakerInvoke(Invoker<?> invoker, Invocation invocation) throws RpcException { // 首先检查是否需要进入服务降级流程 if (checkNeedCircuitBreak(invoker, invocation)) { logger.info( "[{}] activate the circuit break for url [{}],invoke method [{}]", localHost, invoker.getUrl(), invocation.getMethodName()); // 进入服务降级 return doCircuitBreak(invoker, invocation); } try { Result result = invoker.invoke(invocation); // 将该服务从服务降级中恢复出来 toBeNormal(invoker, invocation); return result; } catch (RpcException e) { // 如果是请求超时或者网络异常,进行异常统计 if (!e.isBiz()) { caughtException(invoker, invocation, e); } throw e; } }
/** * When destroying, RegistryDirectory should: 1. be disconnected from Registry 2. destroy all * invokers */ @Test public void testDestroy() { RegistryDirectory registryDirectory = getRegistryDirectory(); List<URL> serviceUrls = new ArrayList<URL>(); serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1")); serviceUrls.add(SERVICEURL2.addParameter("methods", "getXXX1,getXXX2")); serviceUrls.add(SERVICEURL3.addParameter("methods", "getXXX1,getXXX2,getXXX3")); registryDirectory.notify(serviceUrls); List<Invoker> invokers = registryDirectory.list(invocation); Assert.assertEquals(true, registryDirectory.isAvailable()); Assert.assertEquals(true, invokers.get(0).isAvailable()); registryDirectory.destroy(); Assert.assertEquals(false, registryDirectory.isAvailable()); Assert.assertEquals(false, invokers.get(0).isAvailable()); registryDirectory.destroy(); Map<String, List<Invoker<RegistryDirectoryTest>>> methodInvokerMap = registryDirectory.getMethodInvokerMap(); Map<String, Invoker<RegistryDirectoryTest>> urlInvokerMap = registryDirectory.getUrlInvokerMap(); Assert.assertTrue(methodInvokerMap == null); Assert.assertEquals(0, urlInvokerMap.size()); // List<U> urls = mockRegistry.getSubscribedUrls(); RpcInvocation inv = new RpcInvocation(); try { registryDirectory.list(inv); fail(); } catch (RpcException e) { Assert.assertTrue(e.getMessage().contains("already destroyed")); } }