• dubbo服务降级


    转:

    1. 在 dubbo 管理控制台配置服务降级

    上图的配置含义是:consumer 调用 com.zhang.HelloService 的方法时,直接返回 null,不发起远程调用。

    实际操作是:在 zk 的 /dubbo/com.zhang.HelloService/configurators 节点中添加了 override。

    override://0.0.0.0/com.zhang.HelloService?category=configurators&dynamic=false&group=a&mock=force:return+null

    2. 也可以通过代码,进行服务降级:(dubbo文档中给出了代码片段)

    可以通过服务降级功能,临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
    向注册中心写入动态配置覆盖规则:

    RegistryFactory registryFactory = 
        ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
    Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
    registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=consumer_app&mock=force:return+null"));

    mock=force:return+null
    表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
    mock=fail:return+null
    表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

    dubbo 服务降级的真实含义:并不是对 provider 进行操作,而是告诉 consumer,调用服务时要做哪些动作。

    3. 现在分析consumer端静态配置mock, consumer中如何调用mock服务

    用户可以在<dubbo:reference>中配置mock属性。如何配置自定义的mock,还没有搞懂。以mock="force:return+null"为例,我们先分析dubbo默认的MockInvoker。

    MockClusterInvoker逻辑:

    复制代码
    // MockClusterInvoker
    public Result invoke(Invocation invocation) throws RpcException {
        Result result = null;
        
        // 获取<dubbo:reference>的mock属性。
        String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim(); 
        if (value.length() == 0 || value.equalsIgnoreCase("false")){
            //mock="" 或者 mock="false"
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith("force")) {
            //强制使用mock,如mock="force:return+null"
            if (logger.isWarnEnabled()) {
                logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " +  directory.getUrl());
            }
            result = doMockInvoke(invocation, null);
        } else {
            //mock="fail:return+null" 或 mock="MyMock"
            try {
                result = this.invoker.invoke(invocation);
            }catch (RpcException e) {
                if (e.isBiz()) {
                    throw e;
                } else {
                    if (logger.isWarnEnabled()) {
                        logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " +  directory.getUrl(), e);
                    }
                    //出现超时异常
                    result = doMockInvoke(invocation, e);
                }
            }
        }
        return result;
    }
    
    private Result doMockInvoke(Invocation invocation, RpcException e) {
        Result result = null;
        Invoker<T> minvoker;
        
        List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
        if (mockInvokers == null || mockInvokers.size() == 0){
            //如果没有配置自定义Mock,则使用默认MockInvoker
            minvoker = (Invoker<T>) new MockInvoker(directory.getUrl());
        } else {
            minvoker = mockInvokers.get(0);
        }
        try {
            //调用
            result = minvoker.invoke(invocation);
        } catch (RpcException me) {
            if (me.isBiz()) {
                result = new RpcResult(me.getCause());
            } 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:

    复制代码
    // MockInvoker
    public Result invoke(Invocation invocation) throws RpcException {
        //获取url中的sayHello.mock参数值
        String mock = getUrl().getParameter(invocation.getMethodName() + "." + Constants.MOCK_KEY);
        if (invocation instanceof RpcInvocation) {
            ((RpcInvocation) invocation).setInvoker(this);
        }
        if (StringUtils.isBlank(mock)){
            //获取mock属性值
            mock = getUrl().getParameter(Constants.MOCK_KEY);
        }
        
        if (StringUtils.isBlank(mock)){
            throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url));
        }
        //假定mock="force:return+null",处理后mock="return+null"
        mock = normallizeMock(URL.decode(mock));
        if (Constants.RETURN_PREFIX.trim().equalsIgnoreCase(mock.trim())){
            RpcResult result = new RpcResult();
            result.setValue(null);
            return result;
        } else if (mock.startsWith(Constants.RETURN_PREFIX)) {
            //构造返回值
            mock = mock.substring(Constants.RETURN_PREFIX.length()).trim();
            mock = mock.replace('`', '"');
            try {
                Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
                Object value = parseMockValue(mock, returnTypes);
                return new RpcResult(value);
            } catch (Exception ew) {
                throw new RpcException("mock return invoke error. method:" + invocation.getMethodName() + ", mock:" + mock + ", url: "+ url , ew);
            }
        } else if (mock.startsWith(Constants.THROW_PREFIX)) {
            mock = mock.substring(Constants.THROW_PREFIX.length()).trim();
            mock = mock.replace('`', '"');
            if (StringUtils.isBlank(mock)){
                throw new RpcException(" mocked exception for Service degradation. ");
            } else { //用户自定义类
                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 implemention class " + mock , t);
             }
        }
    }
    
    //mock=fail:throw
    //mock=fail:return
    //mock=xx.Service
    private String normallizeMock(String mock) {
        if (mock == null || mock.trim().length() ==0){
            return mock;
        } else if (ConfigUtils.isDefault(mock) || "fail".equalsIgnoreCase(mock.trim()) || "force".equalsIgnoreCase(mock.trim())){
            mock = url.getServiceInterface()+"Mock";
        }
        if (mock.startsWith(Constants.FAIL_PREFIX)) {
            mock = mock.substring(Constants.FAIL_PREFIX.length()).trim();
        } else if (mock.startsWith(Constants.FORCE_PREFIX)) {
            mock = mock.substring(Constants.FORCE_PREFIX.length()).trim();
        }
        return mock;
    }
    复制代码
    标签: dubbo
  • 相关阅读:
    自己写库—构建库函数雏形
    暑假第二周计划
    初学Oracle
    暑假第一周计划
    读书笔记六
    读书笔记五
    读书笔记四
    读书笔记三
    读书笔记
    系统目标文档
  • 原文地址:https://www.cnblogs.com/libin6505/p/11270147.html
Copyright © 2020-2023  润新知