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;
 }
 private void incrementBreakCount(Invoker<?> invoker, Invocation invocation) {
   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();
   BreakCounter counter = breakCounterMap.get(methodKey);
   counter.incrementBreakCount();
 }
 /**
  * 将服务恢复正常
  *
  * @param invoker
  * @param invocation
  */
 private void toBeNormal(Invoker<?> invoker, Invocation invocation) {
   String interfaceName = invoker.getUrl().getParameter(Constants.INTERFACE_KEY);
   String method = invocation.getMethodName();
   StringBuffer methodConfig = new StringBuffer(Config.DUBBO_REFERENCE_PREFIX);
   methodConfig.append(interfaceName).append(".").append(method);
   String methodKey = methodConfig.toString();
   // 从其中删除对应的异常计数器
   BreakCounter counter = breakCounterMap.remove(methodKey);
   if (counter != null) {
     logger.info("[{}] [{}.{}] to be normal", localHost, interfaceName, methodKey);
     // 将这个counter设置为失效
     counter.disable();
   }
 }