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

作为一个RPC框架,Dubbo同时提供了兼具微服务的一些服务管理功能:
服务降级、限流

服务降级

Dubbo中服务降级可以通过mock实现,在消费端,通过配置mock选项,来支持服务降级
如:

@DubboReference(mock = "force:return null")
@DubboReference(mock = "return null")

@DubboReference(mock = "throw") // 抛出 RpcException
@DubboReference(mock = "throw com.xxx.XXXException")  // 抛出RpcException,并传入自定义异常

@DubboReference(mock = "com.xxx.XXXServiceImpl") // 实现调用接口,mock时调用该实现对应的接口方法

可以通过如上几种方式,其中force是强制mock,不管调用的服务是否正常,都走mock流程,其他的都是在调用失败之后走mock。

mock代码实现在MockClusterInvoker中:

public Result invoke(Invocation invocation) throws RpcException {
        Result result = null;
        String value = getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
        if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith("force")) {
            if (logger.isWarnEnabled()) {
                logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + getUrl());
            }
            result = doMockInvoke(invocation, null);
        } else {
            //fail-mock
            try {
                result = this.invoker.invoke(invocation);
                if(result.getException() != null && result.getException() instanceof RpcException){
                    RpcException rpcException= (RpcException)result.getException();
                    if(rpcException.isBiz()){
                        throw  rpcException;
                    }else {
                        result = doMockInvoke(invocation, rpcException);
                    }
                }
            } catch (RpcException e) {
                if (e.isBiz()) {
                    throw e;
                }
                result = doMockInvoke(invocation, e);
            }
        }
        return result;
    }

可以看到,对于force这种mock,不管服务提供方是否正常都走mock,而具体执行mock在MockInvoker中:

public Result invoke(Invocation invocation) throws RpcException {
        if (invocation instanceof RpcInvocation) {
            ((RpcInvocation) invocation).setInvoker(this);
        }
        String mock = null;
        if (getUrl().hasMethodParameter(invocation.getMethodName())) {
            mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY);
        }
        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 = normalizeMock(URL.decode(mock));
        if (mock.startsWith(RETURN_PREFIX)) {
            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);
            }
        } 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 { 
            try {
                Invoker<T> invoker = getInvoker(mock);
                return invoker.invoke(invocation);
            } catch (Throwable t) {
                throw new RpcException("Failed to create mock implementation class " + mock, t);
            }
        }
    }
服务限流

服务限流,为了防止服务的QPS突然飙升或者太大导致服务频繁失败甚至崩溃重启,对一些重要服务进行限流,虽然会导致一些请求失败,但是能够保证服务平稳运行
Dubbo中的限流有如下几个措施:

accepts:限制服务器端接受的连接数,对于服务提供方,Dubbo默认基于Netty协议的底层网络可以限制客户端连接数量进行限制dubbo.protocol.accepts=10 或者dubbo.provider.accepts=10 只能在服务提供端

connections:限制客户端服务使用连接数,使用@DubboReference(connections = 10)或者
@DubboService(connections = 10) 作用在接口或方法级别上,如果两个都有,@DubboReference(connections = 10)优先

executes: 服务提供者并发限制,作用在服务提供者接口或者方法上,@DubboService(connections = 10,executes = 10)@Method(executes = 10),Dubbo中会根据接口或者方法上的该配置,然后在每次执行方法前,会判断当前接口或者方法并行的数量是否大于该值,如果大于抛出异常,否则当前接口和方法active+1.在ExecuteLimitFilter实现了该过滤处理

actives:与executes类似,但是可以作用在服务提供者和消费者的接口或方法上,但是不同于executes不同的是,这里是表示同事能够活跃的处理数,如果超过该值,则需要等待timeoutms,超时则抛出异常,在ActiveLimitFilter实现了active处理

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值