结合源码分析 bubble 使用注意事项
使用dubbo时候要尽量了解源码,不然会很容易入坑。
一、服务消费端ReferenceConfig需要自行缓存
ReferenceConfig实例是个很重的实例,每个ReferenceConfig实例里面都维护了与服务注册中心的一个长链,并且维护了与所有服务提供者的的长链。假设有一个服务注册中心和N个服务提供者,那么每个ReferenceConfig实例里面维护了N+1个长链,如果频繁的生成ReferenceConfig实例,可能会造成性能问题,甚至产生内存或者连接泄露的风险。特别是使用dubbo api编程时候容易忽略这个问题。
为了解决这个问题,之前都是自行缓存,但是自从dubbo2.4.0版本后,dubbo 提供了简单的工具类 ReferenceConfigCache 用于缓存ReferenceConfig 实例。使用如下:
/创建服务消费实例
ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>();
reference.setInterface(XxxService.class);
reference.setVersion("1.0.0");
......
//获取dubbo提供的缓存
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
// cache.get方法中会缓存 reference对象,并且调用reference.get方法启动ReferenceConfig,并返回经过代理后的服务接口的对象
XxxService xxxService = cache.get(reference); // 使用xxxService对象
xxxService.sayHello();
需要注意的是 Cache内持有ReferenceConfig对象的引用,不要在外部再调用ReferenceConfig的destroy方法了,这会导致Cache内的ReferenceConfig失效!
如果要销毁 Cache 中的 ReferenceConfig ,将销毁 ReferenceConfig 并释放对应的资源,具体使用下面方法来销毁
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
cache.destroy(reference);
另外以服务 Group、接口、版本为缓存的 Key,ReferenceConfig实例为对应的value。如果你需要使用自定义的key,可以在创建cache时候调用ReferenceConfigCache cache = ReferenceConfigCache.getCache(keyGenerator );方法传递自定义的keyGenerator。
二、 并发控制
2.1 服务消费方并发控制 在服务消费方法进行并发控制需要设置actives参数,如下:
<dubbo:reference id="userService" interface="com.test.UserServiceBo"
group="dubbo" version="1.0.0" timeout="3000" actives="10"/>
设置com.test.UserServiceBo接口中所有方法,每个方法最多同时并发请求10个请求。
也可以使用下面方法设置接口中的单个方法的并发请求个数,如下:
<dubbo:reference id="userService" interface="com.test.UserServiceBo"
group="dubbo" version="1.0.0" timeout="3000">
<dubbo:method name="sayHello" actives="10" />
</dubbo:reference>
如上设置sayHello方法的并发请求数量最大为10,如果客户端请求该方法并发超过了10则客户端会被阻塞,等客户端并发请求数量少于10的时候,该请求才会被发送到服务提供方服务器。在dubbo中客户端并发控制是使用ActiveLimitFilter过滤器来控制的,代码如下:
public class ActiveLimitFilter implements Filter { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
URL url = invoker.getUrl();
String methodName = invocation.getMethodName();
//获取设置的acvites的值,默认为0
int max = invoker.getUrl().getMethodParameter(methodName, Constants.ACTIVES_KEY, 0);
//获取当前方法目前并发请求数量
RpcStatus count = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
if (max > 0) {//说明设置了actives变量
long timeout = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.TIMEOUT_KEY, 0);
long start = System.currentTimeMillis();
long remain = timeout;
int active = count.getActive();
//如果该方法并发请求数量大于设置值,则挂起当前线程。
if (active >= max) {
synchronized (count) {
while ((active = count.getActive()) >= max) {
try {
count.wait(remain);
} catch (InterruptedException e) {
}
//如果等待时间超时,则抛出异常
long elapsed = System.currentTimeMillis() - start;
remain = timeout - elapsed;
if (remain <= 0) {
throw new RpcException("Waiting concurrent invoke timeout in client-side for service: "
+ invoker.getInterface().getName() + ", method: "
+ invocation.getMethodName() + ", elapsed: " + elapsed
+ ", timeout: " + timeout + ". concurrent invokes: " + active
+ ". max concurrent invoke limit: " + max);
}
}
}
}
}
//没有限流时候,正常调用
try {
long begin = System.currentTimeMillis();
RpcStatus.beginCount(url, methodName);
try {
Result result = invoker.invoke(invocation);
RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, true);
return result;
} catch (RuntimeException t) {
RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, false);
throw t;
}
} finally {
if (max > 0) {
synchronized (count) {
count.notify();
}
}
}
} }
可知客户端并发控制,是如果当并发量达到指定值后,当前客户端请求线程会被挂起,如果在等待超时期间并发请求量少了,那么阻塞的线程会被激活,然后发送请求到服务提供方,如果等待超时了,则直接抛出异常,这时候服务根本都没有发送到服务提供方服务器。
三、 改进的广播策略
前面我们讲解集群容错时候谈到有一个广播策略,该策略主要用于对所有服务提供者进行广播消息,那么有个问题需要思考,广播是是说你在客户端调用接口一次,内部就是轮询调用所有服务提供者的机器的服务,那么你调用一次该接口,返回值是什么那?比如内部轮询了10台机器,每个机器应该都有一个返回值,那么你调用的这一次返回值是10个返回值的组成?其实不是,返回的是轮询调用的最后一个机器结果,那么如果我们想把所有的机器返回的结果聚合起来如何做的?
结合源码分析 bubble 使用注意事项的更多相关文章
- jQuery源码分析系列(36) : Ajax - 类型转化器
什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...
- jQuery-1.9.1源码分析系列(二)jQuery选择器
1.选择器结构 jQuery的选择器根据源码可以分为几块 init: function( selector, context, rootjQuery ) { ... // HANDLE: $(&quo ...
- List 接口以及实现类和相关类源码分析
List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...
- ZRender源码分析3:Painter(View层)-上
回顾 上一篇说到:ZRender源码分析2:Storage(Model层),这次咱看来看看Painter-View层 总体理解 Painter这个类主要负责MVC中的V(View)层,负责将Stora ...
- 一个普通的 Zepto 源码分析(三) - event 模块
一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...
- Android源码分析—深入认识AsyncTask内部机制
本文转载http://blog.csdn.net/singwhatiwanna/article/details/17596225该博主博文,谢谢该博主提供的好文章! 前言 什么是AsyncTask,相 ...
- [源码分析]AbstractStringBuilder
[源码分析]AbstractStringBuilder Java中, AbstractStringBuilder是 StringBuilder 和 StringBuffer 的父类. 所以了解Stri ...
- django Rest Framework----APIView 执行流程 APIView 源码分析
在django—CBV源码分析中,我们是分析的from django.views import View下的执行流程,这篇博客我们介绍django Rest Framework下的APIView的源码 ...
- 并发-ConcurrentHashMap源码分析
ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...
随机推荐
- Cassandra--启用用户认证和用户管理
======================================================== 启用用户认证和创建超级用户 需要针对每个节点进行配置修改和重启,但授权操作仅需要在任一 ...
- 你不知道的JavaScript(中卷) (Kyle Simpson 著)
第一部分 类型和语法 第1章 类型 1.1 类型 1.2 内置类型 1.3 值和类型 1.3.1 undefined和undeclared 1.3.2 typeof Undeclared 1.4 小结 ...
- c++内存泄漏原因及解决办法(智能指针)
内存泄漏 由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费. 内存泄露的 ...
- 自动化测试神器 之 python unittest 断言
自动化测试的最后一步需要判断结果是否正确,而正确设置断言可以帮助判断测试用例的执行结果,从而提高自动化测试的效率,python unittest 提供了一个比较完整的断言方法.unittest框架测 ...
- Java变量的初始值
Java中的变量如果没有赋值,成员变量默认被初始化,局部变量则不会. 对于成员变量 int a; // a的初始值为0 如下例中的成员变量a,b,c,d public class Va ...
- 大数据离线分析平台 JSSDK数据收集引擎编写
JsSDK设计规则在js sdk中我们需要收集launch.pageview.chargeRequest和eventDuration四种数据,所以我们需要在js中写入四个方法来分别收集这些数据,另外我 ...
- ionic cordova platform --help
ionic platform add android 给我报这个问题,不理解 The platform command has been renamed. To find out more, run: ...
- 【转】jumpserver 堡垒机环境搭建(图文详解)
jumpserver 堡垒机环境搭建(图文详解) 摘要: Jumpserver 是一款由python编写开源的跳板机(堡垒机)系统,实现了跳板机应有的功能.基于ssh协议来管理,客户端无需安装ag ...
- oracle--合并行数据(拼接字符串),获取查询数据的前3条数据...
--标准函数Lpad 可以实现左补零,但是如果多于需要长度,则会截断字符串 SELECT LPAD ('1' , 3 , '0') FROM DUAL -- return 001 情况一:需要补零. ...
- VirtualBox 虚拟机复制
本文简单讲两种情况下的复制方式 1 跨电脑复制 2 同一virtrul box下 虚拟机复制 ---------------------------------------------- 1 跨电脑复 ...