博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Dubbo源码之服务端并发控制——ExecuteLimitFilter
阅读量:6537 次
发布时间:2019-06-24

本文共 2826 字,大约阅读时间需要 9 分钟。

hot3.png

上一篇关于 作用,设计原理,及配置方式。

这篇是关于Dubbo服务端Filter组件扩展 ExecuteLimitFilter ,它可以限制服务端的方法级别的并发处理请求数。 当请求数超过限制时,服务端采用的是非阻塞处理,如果超出并发数量,则直接进行失败处理(这里抛RPCException异常),这里与客户端限流ActiveLimitFilter 的wait不同的是,这里采用Semaphore 信号量的方式,并且是抢占式的(NonFairSync) , 不明白的可以看下信号量相关源码。

同分析ActiveLimitFilter一样,首先看它的Activate注解信息 :

@Activate(group = Constants.PROVIDER, value = Constants.EXECUTES_KEY)

这里可以得知它是用于服务端限流控制。

ActiveLimitFilter源码:

/** * ThreadLimitInvokerFilter * * @author william.liangf */@Activate(group = Constants.PROVIDER, value = Constants.EXECUTES_KEY)public class ExecuteLimitFilter implements Filter {    public Result invoke(Invoker
invoker, Invocation invocation) throws RpcException { URL url = invoker.getUrl(); String methodName = invocation.getMethodName(); Semaphore executesLimit = null; boolean acquireResult = false; //默认不设置executes时候,其值为0 int max = url.getMethodParameter(methodName, Constants.EXECUTES_KEY, 0); if (max > 0) { //max>0说明设置了executes值 RpcStatus count = RpcStatus.getStatus(url, invocation.getMethodName());// if (count.getActive() >= max) { /** * http://manzhizhen.iteye.com/blog/2386408 * 通过信号量来做并发控制(即限制能使用的线程数量) * 2017-08-21 yizhenqiang */ 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
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(); } } }}

当请求并发数大于最大并发数时,则直接失败处理。

服务提供方进行并发控制配置方式如下:

设置com.alibaba.dubbo.demo.DemoService 接口中的所有方法,最多同时处理10个并发请求。

也可以通过如下方式单独对每个方法进行并发控制:

这里我们采用Semaphore来进行服务端请求的并发控制, 而不是采用 sync 同步代码块 , wait notify 方式的目的是什么呢?

这里Semaphore 代替 sync 实际上是 cas 代替 锁 + wait notify  ,  虽然Semaphore中底层采用的是单线程CAS , 等待线程LockSupport.park(this); 防止所有线程同时获取令牌的CPU资源消耗。  源码参考之前写的一篇 AQS源码介绍:

 

赞赏支持

转载于:https://my.oschina.net/LucasZhu/blog/1934009

你可能感兴趣的文章