DUBBO

dubbo是如何控制并发数和限流的?

ExecuteLimitFilterExecuteLimitFilter,在服务提供者,通过的"executes"统一配置项开启:表示每服务的每方法最大可并行执行请求数。ExecuteLimitFilter是通过信号量来实现的对服务端的并发数的控制。ExecuteLimitFilter执行流程:1:首先会去获得服务提供者每服务每方法最大可并行执行请求数2:如果每服务每方法最大可

ExecuteLimitFilter

ExecuteLimitFilter ,在服务提供者,通过 的 "executes" 统一配置项开启:
表示每服务的每方法最大可并行执行请求数。

ExecuteLimitFilter是通过信号量来实现的对服务端的并发数的控制。

4f4608f1a92e864d6998b039616336e8.png

ExecuteLimitFilter执行流程:

1:首先会去获得服务提供者每服务每方法最大可并行执行请求数

2:如果每服务每方法最大可并行执行请求数大于零,那么就基于基于服务 URL + 方法维度获取一个RpcStatus实例

3:通过RpcStatus实例获取一个信号量,若果获取的这个信号量调用tryAcquire返回false,则抛出异常

4:如果没有抛异常,那么久调用RpcStatus静态方法beginCount,给这个 URL + 方法维度开始计数

5:调用服务

6:调用结束后计数调用RpcStatus静态方法endCount,计数结束

7:释放信号量

ExecuteLimitFilter源码如下:

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        URL url = invoker.getUrl();
        String methodName = invocation.getMethodName();
        Semaphore executesLimit = null;
        boolean acquireResult = false;
        int max = url.getMethodParameter(methodName, Constants.EXECUTES_KEY, 0);
        if (max > 0) {
            RpcStatus count = RpcStatus.getStatus(url, invocation.getMethodName());
//            if (count.getActive() >= max) {
            /**
             * http://manzhizhen.iteye.com/blog/2386408
             * use semaphore for concurrency control (to limit thread number)
             */
            executesLimit = count.getSemaphore(max);
            if(executesLimit != null && !(acquireResult = executesLimit.tryAcquire())) {
                throw new RpcException("Failed to invoke method " + invocation.getMethodName() + " in provider " + url + ", cause: The service using threads greater than <dubbo:service executes=\"" + max + "\" /> limited.");
            }
        }
        long begin = System.currentTimeMillis();
        boolean isSuccess = true;
        RpcStatus.beginCount(url, methodName);
        try {
            Result result = invoker.invoke(invocation);
            return result;
        } catch (Throwable t) {
            isSuccess = false;
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new RpcException("unexpected exception when ExecuteLimitFilter", t);
            }
        } finally {
            RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, isSuccess);
            if(acquireResult) {
                executesLimit.release();
            }
        }
    }

我们接下来看看RpcStatus这个类

    private

原创不易,完成人机校验,阅读全文

相关推荐