dubbo服务降级

Posted libin6505

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于dubbo服务降级的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo中服务降级服务限流限流措施

Dubbo服务降级

「DUBBO系列」服务降级源码分析

Dubbo3高级特性「框架与服务」 针对出现异常的RPC的服务功能降级机制

dubbo服务降级

Dubbo 支持服务降级吗?