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,这种时候就可以直接取到方法配置的值。
当数量合法的时候,则表示可以正常的执行方法
网友评论