private void caughtException(Invoker<?> invoker, Invocation invocation, Exception e) { String interfaceName = invoker.getUrl().getParameter(Constants.INTERFACE_KEY); String method = invocation.getMethodName(); StringBuffer interfaceConfig = new StringBuffer(Config.DUBBO_REFERENCE_PREFIX); interfaceConfig.append(interfaceName); StringBuffer methodConfig = new StringBuffer(interfaceConfig.toString()); methodConfig.append(".").append(method); String methodKey = methodConfig.toString(); int timeout = invoker .getUrl() .getMethodParameter( invocation.getMethodName(), Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); int limit = Config.getBreakLimit(invoker, invocation); // 一个异常的有效期,是通过连续出现异常数量乘以每个调用的超时时间,比如你配置连续出现10次异常之后进行服务降级,并且每次服务调用的超时时间是2000ms的话,同时 // 每个服务重试次数是为2次,那么就是在(2+1)*2000*10 ExceptionMarker breakMarker = new ExceptionMarker(System.currentTimeMillis(), limit * timeout, e); if (!breakCounterMap.containsKey(methodKey)) { BreakCounter oldValue = breakCounterMap.putIfAbsent(methodKey, new BreakCounter(methodKey)); // 返回的oldValue为空,表示之前没有创建了赌赢的异常计数器,则需要对它分配一个loop if (oldValue == null) { nextLoop().register(breakCounterMap.get(methodKey)); } } BreakCounter counter = breakCounterMap.get(methodKey); counter.addExceptionMarker(breakMarker); logger.info( "[{}] caught exception for rpc invoke [{}.{}],current exception count [{}]", localHost, interfaceName, method, counter.getCurrentExceptionCount()); }
/** * 这里会判断当前调用服务的状态,分析判断是否需要进入降级状态 如果服务在指定的时间区间内累积的错误,达到了配置的次数,则进入服务降级 * 如果满足上面条件,并且满足重试机制,则也不会进入降级流程,而是触发远程服务调用 * * @param invoker * @param invocation * @return */ private boolean checkNeedCircuitBreak(Invoker<?> invoker, Invocation invocation) { String interfaceName = invoker.getUrl().getParameter(Constants.INTERFACE_KEY); String method = invocation.getMethodName(); String methodKey = Config.getMethodPropertyName(invoker, invocation).toString(); int limit = Config.getBreakLimit(invoker, invocation); BreakCounter breakCounter = breakCounterMap.get(methodKey); if (breakCounter != null && breakCounter.isEnable()) { long currentExceptionCount = breakCounter.getCurrentExceptionCount(); long currentBreakCount = breakCounter.getCurrentBreakCount(); logger.info( "[{}] check invoke [{}.{}] circuit break,current exception count [{}] limit [{}]", localHost, interfaceName, method, currentExceptionCount, limit); if (limit <= currentExceptionCount) { if (currentBreakCount > 0 && needRetry(invoker, invocation, currentBreakCount)) { logger.info( "[{}] retry invoke [{}.{}] current break count [{}]", localHost, interfaceName, method, currentBreakCount); breakCounter.incrementRetryTimes(); return false; } return true; } } return false; }