美文网首页
Dubbo源码分析----过滤器之ExecuteLimitFil

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

作者: _六道木 | 来源:发表于2018-07-17 02:02 被阅读18次

    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,这种时候就可以直接取到方法配置的值。

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

    相关文章

      网友评论

          本文标题:Dubbo源码分析----过滤器之ExecuteLimitFil

          本文链接:https://www.haomeiwen.com/subject/cqgipftx.html