`
manzhizhen
  • 浏览: 289515 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Dubbo源代码分析七:使用executes属性的一个问题

阅读更多

我们知道,在Dubbo中可以给Provider配置线程池大小来控制系统提供服务的最大并行度,默认是200个,如果我们想配置成500,可以如下配置:

 

<dubbo:provider token="true" threads="500"/>

 

当我们想限制某个dubbo服务使用的最大线程数量时,dubbo提供了executes这一属性来提供这个功能,比如我们想限制某个接口最大能同时使用线程池中的100个线程,我们可以如下配置:

 

<dubbo:service interface="com.manzhizhen.service.MyLoverService" executes="100" />

 

我们看下dubbo内部executes是如何实现的,这就得移步到ExecuteLimitFilter,我们直接看下它的实现:

@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();

        int max = url.getMethodParameter(methodName, Constants.EXECUTES_KEY, 0);

        // 如果该接口/方法设置了executes并且值大于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;

        // 计数器+1

        RpcStatus.beginCount(url, methodName);

        try {

            Result result = invoker.invoke(invocation);

            return result;

        } catch (Throwable t) {

            isException = true;

            if (t instanceof RuntimeException) {

                throw (RuntimeException) t;

            } else {

                throw new RpcException("unexpected exception when ExecuteLimitFilter", t);

            }

        } finally {

            // finally中进行计数器-1

            RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, isException);

        }

    }

}

 

看上面的代码,可以得知基本步骤就是(黄底的部分代码):计数器当前值和阈值比较 > 计数器+1 > 计数器-1。这种方式在高并发时会出现静态条件问题的,比如当前该接口已经使用了99个线程,这是时候有两个请求同时到达都发现count.getActive()是小于max的,于是该接口使用的线程数就有可能达到了101个。

 

那么,我们能不能把RpcStatus.beginCount(url, methodName);放到count.getActive() >= max的前面去执行?仔细想想后也不行,这样做的话有可能在高并发时请求被count.getActive() >= max卡死,因为大量请求将计数器+1+1的速度远大于原有请求执行完将计数器-1的速度),导致一段时间内计数器一直大于阈值但实际上该接口使用的线程数却是0

 

于是,为了将比较和+1做成原子的,我们想到了Semaphore信号量Semaphore维护了一组许可,用来管理有限的资源,比如这里的线程数。使用Semaphore的有两点需要注意的地方,第一个就是说如果使用不当会导致Semaphore中的许可数多于最初设置的值,或者变为负数,也就是说,Semaphore并没有对非正常使用作出任何保护措施。还有一点是Semaphore没有方法能直接修改许可数量,但我们可以通过间接方法(比如多release几次以增加许可数量),但毕竟不优雅。

 

<!--StartFragment--> <!--EndFragment-->

Semaphore可以解决上述问题,但当需要修改线程数时,我们应该新建一个Semaphore对象,当采用这种替换Semaphore对象来应对许可数的变化时,一定要确保在仍和情况下acquire和release操作应该在一个Semaphore对象上。这也是我们在设计那些控制并发的小工具时需要注意的地方。

0
0
分享到:
评论
5 楼 manzhizhen 2017-08-12  
yingwuluohan 写道
楼主,我还想请教个问题,一起分析下。
场景是几台台分布式部署的集群服务器,rpc通信用的dubbo,生产和消费也都按照dubbo框架的消费生产模式拆分的。目前运行的进程在上线几周后经常出现服务调用超时的情况,查询数据库监控并没有发现DB有锁表的情况,服务器cpu也正常。在重启应用服务器后超时的现象消失,应用又正常了。
  我几次想在问题发生时下载服务器的内存快照,想找出具体是应用的哪个对象占用了资源。不知道楼主熟悉java堆栈的监控的工具吗?能不能推荐一下,另外就是JVM的调优,当时也考虑到是不是GC没有及时回收导致的,我始终没有找到合适的工具分析内存快照,还有就是怎么样去权衡JVM的配置是否合适


先通过gc日志看是否是gc时间过长导致的超时,如果不是gc原因,可以通过请求日志来判断是否是网络耗时(consumer处理耗时-provider处理耗时)导致。如果不是gc和网络原因,看是否代码内部有什么锁或者队列导致的耗时增加,需要具体情况具体分析。
4 楼 yingwuluohan 2017-08-11  
楼主,我还想请教个问题,一起分析下。
场景是几台台分布式部署的集群服务器,rpc通信用的dubbo,生产和消费也都按照dubbo框架的消费生产模式拆分的。目前运行的进程在上线几周后经常出现服务调用超时的情况,查询数据库监控并没有发现DB有锁表的情况,服务器cpu也正常。在重启应用服务器后超时的现象消失,应用又正常了。
  我几次想在问题发生时下载服务器的内存快照,想找出具体是应用的哪个对象占用了资源。不知道楼主熟悉java堆栈的监控的工具吗?能不能推荐一下,另外就是JVM的调优,当时也考虑到是不是GC没有及时回收导致的,我始终没有找到合适的工具分析内存快照,还有就是怎么样去权衡JVM的配置是否合适
3 楼 yingwuluohan 2017-08-04  
manzhizhen 写道
yingwuluohan 写道
楼主,RpcStatus 中所有对计数的方法全部都是静态的,这样做与给方法加锁的效果是一样的吗?

静态方法和线程安全的方法是没有直接联系的。

我理解错了
2 楼 manzhizhen 2017-07-29  
yingwuluohan 写道
楼主,RpcStatus 中所有对计数的方法全部都是静态的,这样做与给方法加锁的效果是一样的吗?

静态方法和线程安全的方法是没有直接联系的。
1 楼 yingwuluohan 2017-07-28  
楼主,RpcStatus 中所有对计数的方法全部都是静态的,这样做与给方法加锁的效果是一样的吗?

相关推荐

    dubbo示例代码dubbo-sample

    dubbo示例代码dubbo-sample

    Dubbo源代码分析之远程调用过程(2.5.4开发版)

    该文档分析了 Dubbo 框架中 RPC 调用的整个流程,并基于源代码按照执行 时序进行说明,源码版本为2.5.4开发版。 涉及的关键点包括:Invocation、Invoker、Directory、路由、负载均衡、集群容错、过滤器以及监控模块...

    Dubbo源代码(2.5.4)

    Dubbo的源代码打包,2.5.4开发发布版,及与Maven构建,本人亲测,可以编译通过。

    Dubbo源代码(2.8.4)

    Dubbo的源代码打包,2.8.4开发发布版,及与Maven构建,本人亲测,可以编译通过。

    dubbo源代码

    dubbo分布式服务框架,方便大家对分布式服务的学习,方便对dubbo的扩展

    dubbo2.8.4.jar

    如果使用dubbo遇到错误:com.alibaba.dubbo.remoting.RemotingException: Fail to decode request due to: RpcInvocation 请下载这个jar,替换掉你项目中的那个jar,应该可以解决。

    dubbo入门源代码

    apache dubbo官网最简单的小例子,只是按照说明弄了下。

    Spring+mybatis+dubbo整合源代码及jar包

    此框架为Spring4.1.6+mybatis3.2.8+dubbo2.5.3的框架源码以及依赖的包

    Dubbo工程demo

    dubbodemo-facede : 定义接口,这个项目是要打成jar包分别被dubbodemo-service和dubbodemo-web引用的 dubbodemo-service : 只做逻辑实现,也就是dubbo中的生产者 dubbodemo-web : 负责页面跳转及渲染,也就是dubbo中的...

    SSM+dubbo项目源代码

    SSM+dubbo项目源代码

    dubbo 文档静态页面源代码。

    gitbooks对中国人体验不友好,如下地址报404的可以下载此资源。...https://dubbo.gitbooks.io/dubbo-user-book/ https://dubbo.gitbooks.io/dubbo-admin-book/ https://dubbo.gitbooks.io/dubbo-dev-book/

    dubbo教程代码案例

    dubbo教程代码demo

    dubbo-admin-2.5.4及dubbo-monitor-2.5.3 安装及配置

    本人实际测试过,这两个包可用。 环境描述:centos6/64位,JDK1.8,tomcat8 dubbo-admin安装要点: 1.清空tomcat/webapps/ROOT目录 2.将包解压到tomcat/webapps/ROOT下 3.修改tomcat/webapps/ROOT/WEB-INF/dubbo....

    dubbo.xsd文件

    targetNamespace="http://code.alibabatech.com/schema/dubbo"&gt; &lt;xsd:import namespace="http://www.w3.org/XML/1998/namespace"/&gt; &lt;xsd:import namespace="http://www.springframework.org/schema/beans"/&gt; ...

    从源代码构建Dubbo

    从源代码构建Dubbo

    dubbo-2.5.8-API文档-中英对照版.zip

    赠送源代码:dubbo-2.5.8-sources.jar; 赠送Maven依赖信息文件:dubbo-2.5.8.pom; 包含翻译后的API文档:dubbo-2.5.8-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:com.alibaba:dubbo:2.5.8; 标签:...

    最简单的Dubbo案例之二:SpringBoot + dubbo 无zookeeper方式点对点直连

    本项目只适合dubbo入门学习者,高手请不要浪费金钱; 本项目技术栈 springboot, dubbo ,无 zookeeper 本项目旨在提供最单纯的 dubbo 服务提供者 和消费者的点对点直连,而摒弃任何多余技术对dubbo直连的理解

    dubbo server+client 完整代码

    dubbo入门完整实例,从发布到调用,代码完全实现。

    阿里巴巴dubbo-2.5.4源代码

    阿里巴巴dubbo2.5.4源代码,内部包含各种demo! 包含dubbo-admin等模块

    dubbo-2.6.1-API文档-中文版.zip

    赠送源代码:dubbo-2.6.1-sources.jar; 赠送Maven依赖信息文件:dubbo-2.6.1.pom; 包含翻译后的API文档:dubbo-2.6.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:com.alibaba:dubbo:2.6.1; 标签:alibaba、...

Global site tag (gtag.js) - Google Analytics