1. 功能特性一览
- 实现rpc调用,像调用本地方法一样调用远程server上的方法
- 支持多协议:(Dubbo、Rmi、Http、Webservice、Redis等等)用户可以根据业务场景选择合适的协议
- 并发高性能:默认Dubbo协议支持,Netty实现,Provider、Consumer、Register之间彼此保持长连接
- 解耦和伸缩性:利用注册中心,实现Provider和Consumer之间解耦,也实现Providers之间的解耦,从而实现灵活的扩展和缩容
- 负载均衡:4种策略配合权重,而且支持代码配置和Dubbo控制台动态配置
- 高可用:利用注册中心发现功能,一个provider挂了的话,会自动被剔除掉,保证服务器继续对外提供服务,如果重新provider重新恢复的话,又恢复到服务提供队列当中了
- 容错: 支持failover、failfast、forking等容错机制,引入retry和timeout参数配置
- 并发控制:服务端(executors、accepts参数)和消费端(actives)都支持不同形式的并发控制
- 调用结果缓存:消费端支持配置3种策略的结果缓存
- 异步调用:支持阻塞和非阻塞将来式返回Future对象的两种调用方式
- 支持权限配置功能:比如白名单功能
2. Dubbo 原理浅析(基于Dubbo协议)
看起来像是BIO阻塞,其实是异步的NIO
1. 每个Provider就是一个Nio的Server,内部机制由Netty实现(也可以是Mina等),两个线程组工作。Provider启动的时候,结合注册中心,暴露对外服务。
2. Consumer的一个线程发起请求,会获取一个全局的线程ID,然后会把该请求的接口名称、方法名称、参数值等信息封装成一个object的对象
3. 把 ID,请求Object放在全局的ConcurrentHashMap里面,发起异步的调用,自身用object为锁对象,wait请求线程进入阻塞状态
4. 调用成功后,触发客户端的监听,然后根据全局ConcurrentHashMap中ID找到object,设置好返回值和回调方法的时候,notifyAll调用的阻塞线程,完成调用
3. Dubbo的容错性
通过在consumer里面配置策略,来实现不同的容错措施,只罗列了3种
I. failover 超时失败自动切换 (缺省值,默认失败后再重试2次)(会导致重复写)
这种方式通常用于读操作,而不是写操作. 因为用在写操作,可能为导致重复写。
如果其中一个Provider 超时回复了,会自动切换到其他的Provider节点,业务并不会停摆,如果Provider集群中只有1个Node,则会重复调用这个Provider
如果其中一个Provider 调用报错了,则直接调用失败,也不会去尝试切换,这个和超时不是一个概念
<dubbo:reference id="demoService" interface="..." cluster="failover" retries="2"/>
II. Forking 并行调用多个服务器,只要一个成功即返回。(会导致重复写)
通常用于实时性要求较高的读操作,但需要浪费更多服务资源
III. failfast 快速失效
只发起一次调用,失败立即报错。通常用于非幂等性写操作,比如说新增记录。
但是这里也会有问题的,如果是因为网络问题,Provider的响应时间慢,Consumer以为调用失败了,但是Provider却调用成功了,涉及到分布式事务的问题。
如果是因为Provider报错的话,倒没事,因为两边都显示执行失败。
配置的方法(配置cunsumer的配置文件):
<dubbo:reference id="demoService" interface="...” cluster="forking" />
Dubbo 负载均衡策略
一般不通过代码xml里面配置,而是通过web界面,动态的选择均衡策略和权重,这样更灵活
1. Random LoadBalance,按照权重随机分配Provider,比如随机且权重是 2:1,那么运行30此,大约有20次在Node1上10次在Node2上。
2. RoundRobin LoadBalance 按照权重轮询分配,如果权重一样就按照取模。比如权重2:1,那么运行30此,一定有20次在Node1上10次在Node2上。
3. LeastActive LoadBalance 节点越活跃越分配更多,避免慢节点堆积
4. ConsistentHash LoadBalance 对第一个参数做Hash计算,每次都访问相同的Provider节点,如果该节点挂了,会均摊到其它节点
配置的方式
1. xml配置:同时支持服务端和客户端配置(如果都配置以客户端配置为主);不仅支持接口级别的总配置,也可以具体到该接口下面的某一个方法
2. dubbo控制台配置,不需要在代码中配置,可以灵活调整
Dubbo 并发控制
客户端并发控制:actives参数
参考源码:ActiveLimitFilter
1. 设置UserServiceBo接口中所有方法,每个方法最多同时并发请求10个请求
2. 如果客户端请求该方法并发超过了10则客户端会被阻塞(count.wait),等客户端并发请求数量少于10的时候,该请求才会被发送到服务提供方服务器
3. 如果等待时间超时,则抛出异常,这时候服务根本都没有发送到服务提供方服务器。
<dubbo:reference interface="..." actives="10"/>
服务端并发控制:executes参数
1. 服务端并发执行(或占用线程池线程数)不能超过10个,超过的话,直接报错
2. 源码参考ExecuteLimitFilter
3. 设置dubbo协议的时候,支持设置最大长连接数(不同于并发执行数)
<dubbo:service interface="..." executes="10" />
<dubbo:protocol name="dubbo" accepts="1000" />
常用协议
不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议
Dubbo协议(默认)
1. Transporter(传输层):mina, netty, grizzy:默认Netty(3.2.5)
2. Serialization: Hessian2 serialization
3. 单一链接、长连接、TCP
4. 适合小数据量(数据小于100k)、高并发的业务场景
5. 支持自定义配置消费端长连接的个数和服务端最大支持的长连接总数
6. 默认Dubbo协议支持:消费者、服务提供者、注册中心之间的长连接,高性能支持并发请求。消费者、服务提供者和监控中心是短连接。
rmi协议(java标准的)
1. 多连接、短连接、BIO连接、基于http协议,适合并发量不大的业务场景
2. 约束:参数和返回值必须实现Java的序列化
其它高级特性
Dubbo 结果缓存(支持3种策略:LRU、FIFO、LFU)
Dubbo的缓存是在服务消费者调用端进行配置的,因为只有业务端才知道自己业务,然后配置相应的策略
<dubbo:reference id="demoService" interface="..." cache="lru" />
白名单功能
1. maven项目需要在resources 下创建 META-INF\dubbocom.alibaba.dubbo.rpc.Filter文件
dubboContextFilter=com.mor.server.dubbo.service.AuthorityFilter
2. 重写Filter方法
Dubbo超时设置
1. 在dubbo的provider和consumer的配置文件中,如果都配置了timeout的超时时间,dubbo默认以consumer中配置的时间为准
2. 默认调用超时重试的时间: 1s,未响应就重试。
3. provider中代码的执行不会因为超时而中断,在执行完毕后,会得到一个dubbo的警告。所以存在分布式事务的一致性问题
<dubbo:service interface="..." ref="helloService" timeout="300"/>
参考资料
https://blog.csdn.net/zgliang88/article/details/75440043
https://www.cnblogs.com/heben/p/7887664.html //容错性