Dubbo服务降级源码阅读

441 阅读3分钟

服务降级常见设置

  • **mock="force:return null":**消费方对该服务的方法调用都直接强制性返回 null 值,不发起远程调用。
  • **mock="fail:return null":**消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。
  • **mock="true":**消费方对该服务的方法调用在失败后,会调用消费方定义的服务降级Mock 类实例的相应方法。而该 Mock 类的类名为“业务接口名+Mock”,且放在与接口相同的包中。
  • **mock=降级类的全限定性类名:**与 **mock="true"**功能类似,不同的是,该方式中的降级类名可以是任意名称,在任何包中

InvokerInvocationHandler.java

image-20210125165021131

MockClusterInvoker.java

public Result invoke(Invocation invocation) throws RpcException {
    Result result = null;
    // 获取mock属性值
    String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
    // 若没有设置mock属性,或mock属性值为false,则不具有降级功能
    if (value.length() == 0 || value.equalsIgnoreCase("false")) {
        //no mock  直接进行远程调用(不会降级)
        result = this.invoker.invoke(invocation);
    } else if (value.startsWith("force")) {
        // 代表开启强制降级,直接放弃远程调用,执行本地降级方法调用
        if (logger.isWarnEnabled()) {
            logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
        }
        //force:direct mock  直接降级
        result = doMockInvoke(invocation, null);
    } else {
        //fail-mock
        try {  // 远程调用
            result = this.invoker.invoke(invocation);
        } catch (RpcException e) {
            // 远程调用出现异常,则再进行服务降级
            if (e.isBiz()) {
                throw e;
            }

            if (logger.isWarnEnabled()) {
                logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
            }
            // 服务降级
            result = doMockInvoke(invocation, e);
        }
    }
    return result;
}

@SuppressWarnings({"unchecked", "rawtypes"})
private Result doMockInvoke(Invocation invocation, RpcException e) {
    Result result = null;
    Invoker<T> minvoker;
    // 重新再从zk中获取一次最新的invoker
    List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
    // 若仍没有可用的invoker,则创建一个MockInvoker,否则返回第一个可用的invoker
    if (CollectionUtils.isEmpty(mockInvokers)) {
        minvoker = (Invoker<T>) new MockInvoker(directory.getUrl(), directory.getInterface());
    } else {
        minvoker = mockInvokers.get(0);
    }
    try {
      	// 执行降级方法调用,跟踪这里
        result = minvoker.invoke(invocation);
    } catch (RpcException me) {
        if (me.isBiz()) {
            result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation);
        } else {
            throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
        }
    } catch (Throwable me) {
        throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
    }
    return result;
}

MockInvoker.java

public Result invoke(Invocation invocation) throws RpcException {
    // 获取<dubbo:method/>中的mock属性
    String mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY);
    if (invocation instanceof RpcInvocation) {
        ((RpcInvocation) invocation).setInvoker(this);
    }
    // 若<dubbo:method/>中没有设置mock,则获取<dubbo:reference/>中的mock
    // 这里就可以看出,方法级别的设置大于接口级别的设置。
    if (StringUtils.isBlank(mock)) {
        mock = getUrl().getParameter(MOCK_KEY);
    }

    if (StringUtils.isBlank(mock)) {
        throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url));
    }
    // 解析mock中的值,并返回。为下面的业务做准备
    mock = normalizeMock(URL.decode(mock));
    // 处理mock以return开头的情况
    if (mock.startsWith(RETURN_PREFIX)) {
        // 取return后面的内容
        mock = mock.substring(RETURN_PREFIX.length()).trim();
        try {
            Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
            Object value = parseMockValue(mock, returnTypes);
            return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
        } catch (Exception ew) {
            throw new RpcException("mock return invoke error. method :" + invocation.getMethodName()
                    + ", mock:" + mock + ", url: " + url, ew);
        }
        // 处理mock以throw开头的情况
    } else if (mock.startsWith(THROW_PREFIX)) {
        mock = mock.substring(THROW_PREFIX.length()).trim();
        if (StringUtils.isBlank(mock)) {
            throw new RpcException("mocked exception for service degradation.");
        } else { // user customized class
            Throwable t = getThrowable(mock);
            throw new RpcException(RpcException.BIZ_EXCEPTION, t);
        }
    } else { //impl mock  调用自定义降级类
        try {
            // 加载并实例化本地降级类
            Invoker<T> invoker = getInvoker(mock);
            return invoker.invoke(invocation);
        } catch (Throwable t) {
            throw new RpcException("Failed to create mock implementation class " + mock, t);
        }
    }
}

public static String normalizeMock(String mock) {
        if (mock == null) {  // mock为null,则返回null
            return mock;
        }

        mock = mock.trim();

        if (mock.length() == 0) {  // mock为空串,则返回空串
            return mock;
        }

        if (RETURN_KEY.equalsIgnoreCase(mock)) {  // mock为return,则返回returnnull
            return RETURN_PREFIX + "null";
        }

        // mock为true、default、fail或force,则返回default
        if (ConfigUtils.isDefault(mock) || "fail".equalsIgnoreCase(mock) || "force".equalsIgnoreCase(mock)) {
            return "default";
        }

        // mock以fail:开头,则返回fail:后面的子串
        if (mock.startsWith(FAIL_PREFIX)) {
            mock = mock.substring(FAIL_PREFIX.length()).trim();
        }

        // mock以force:开头,则返回force:后面的子串
        if (mock.startsWith(FORCE_PREFIX)) {
            mock = mock.substring(FORCE_PREFIX.length()).trim();
        }

        // 若mock以return或throw,则将反引号替换为双引号
        if (mock.startsWith(RETURN_PREFIX) || mock.startsWith(THROW_PREFIX)) {
            mock = mock.replace('`', '"');
        }

        return mock;
    }



 private Invoker<T> getInvoker(String mockService) {
        Invoker<T> invoker = (Invoker<T>) MOCK_MAP.get(mockService);
        if (invoker != null) {
            return invoker;
        }
        // 加载指定业务接口
        Class<T> serviceType = (Class<T>) ReflectUtils.forName(url.getServiceInterface());
        // 构建出降级类,再加载并实例化
        T mockObject = (T) getMockObject(mockService, serviceType);
        // 将降级实例封装为一个invoker
        invoker = PROXY_FACTORY.getInvoker(mockObject, serviceType, url);
        if (MOCK_MAP.size() < 10000) {
            MOCK_MAP.put(mockService, invoker);
        }
        return invoker;
    }

public static Object getMockObject(String mockService, Class serviceType) {
        // 若mockService的值为default,则构建出降级类名
        if (ConfigUtils.isDefault(mockService)) {
            mockService = serviceType.getName() + "Mock";
        }
        // 加载降级类
        Class<?> mockClass = ReflectUtils.forName(mockService);
        // 若降级类没有实现业务接口,则抛出异常
        if (!serviceType.isAssignableFrom(mockClass)) {
            throw new IllegalStateException("The mock class " + mockClass.getName() +
                    " not implement interface " + serviceType.getName());
        }
        try {
            // 实例化
            return mockClass.newInstance();
        } catch (InstantiationException e) {
            throw new IllegalStateException("No default constructor from mock class " + mockClass.getName(), e);
        } catch (IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
    }