Dubbo源码分析----过滤器之ExecuteLimitFilter

ExecuteLimitFilter主要用来做并发控制

例子1:限制服务 的每个方法,服务器端并发执行(或占用线程池线程数)不能超过 10个,具体配置如下

<dubbo:service interface="com.foo.BarService" executes="10" />

例子2:限制 com.foo.BarService 的 sayHello 方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个:

<dubbo:service interface="com.foo.BarService">
    <dubbo:method name="sayHello" executes="10" />
</dubbo:service>

以上两个例子来copy自dubbo官网,下面通过源码分析Filter如何处理,先看下类的定义

@Activate(group = Constants.PROVIDER, value = Constants.EXECUTES_KEY)
public class ExecuteLimitFilter implements Filter {
    //....
}

该Filter只对服务端有效,且url存有executes参数,才会生效,看下invoke方法

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        URL url = invoker.getUrl();
        String methodName = invocation.getMethodName();
        // 从url中获取该方法限制的数量
        int max = url.getMethodParameter(methodName, Constants.EXECUTES_KEY, 0);
        if (max > 0) {// 如果配置了
            RpcStatus count = RpcStatus.getStatus(url, invocation.getMethodName());// 获取当前并发的数量
            if (count.getActive() >= max) {//如果大于配置的数量,则抛出异常
                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 isException = false;
        RpcStatus.beginCount(url, methodName);// 增加当前方法的并发调用数量
        try {
            Result result = invoker.invoke(invocation);
            return result;
        } catch (Throwable t) {
            //ERROR
        }
        finally {
            RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, isException);// 调用完成后减少该方法的数量
        }
    }

总的来说就是取出配置的数量,然后和当前的数量相比较,看看是否超出。
然后具体看下某些方法的实现

    public int getMethodParameter(String method, String key, int defaultValue) {
        String methodKey = method + "." + key;
       // 通过methodName+executes作为key去map中获取配置的数量
        Number n = getNumbers().get(methodKey);
        if (n != null) {// 一开始为0
            return n.intValue();
        }
        // 通过methodName+executes 获取值
        String value = getMethodParameter(method, key);
        if (value == null || value.length() == 0) {
            return defaultValue;
        }
        int i = Integer.parseInt(value);
        getNumbers().put(methodKey, i);// 更新
        return i;
    }
    public String getMethodParameter(String method, String key) {
        // 通过methodName+executes 获取值
        String value = parameters.get(method + "." + key);
        if (value == null || value.length() == 0) {
            return getParameter(key);// 如果获取不到,则直接更新executes获取值
        }
        return value;
    }
    public String getParameter(String key) {
        String value = parameters.get(key);
        if (value == null || value.length() == 0) {
            value = parameters.get(Constants.DEFAULT_KEY_PREFIX + key);
        }
        return value;
    }

上面几个方法是获取executes值的过程,首先会通过methodName+executes 获取值,如果是例子1的这种情况,取的值为空,那么会直接调用getParameter(key)去取配置的值,如果是例子2中的情况,那么url中有个参数是methodName.executes,这种时候就可以直接取到方法配置的值。

当数量合法的时候,则表示可以正常的执行方法

猜你喜欢

转载自blog.csdn.net/u013160932/article/details/81074322
今日推荐