Dubbo的重试机制
http://dubbo.apache.org/zh-cn/docs/source_code_guide/cluster.html
- Dubbo支持多种失败重试机制:
- Failover Cluster - 失败自动切换
- Failfast Cluster - 快速失败
- Failsafe Cluster - 失败安全
- Failback Cluster - 失败自动恢复
- Forking Cluster - 并行调用多个服务提供者
- Broadcast - 广播轮询调用所有Provider
- 通过在consumer里面配置策略,来实现不同的容错措施
<dubbo:reference id="demoService" interface="com.mor.server.dubbo.service.DemoServer" cluster="forking" />
- Dubbo超时设置(默认2次重试 1s算超时
- 在dubbo的provider和consumer的配置文件中,如果都配置了timeout的超时时间,dubbo默认以consumer中配置的时间为准
- provider中代码的执行不会因为超时而中断,在执行完毕后,会得到一个dubbo的警告。所以存在分布式事务的一致性问题
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService"
timeout="300" retry="2" loadbalance="random" actives="0"/>
容错分析
- failover 超时失败自动切换 (缺省值)(会导致重复写)
这种方式通常用于读操作,而不是写操作. 因为用在写操作,可能为导致重复写。
如果其中一个Provider 超时回复了,会自动切换到其他的Provider节点,业务并不会停摆,如果Provider集群中只有1个Node,则会重复调用这个Provider
如果其中一个Provider 调用报错了,则直接调用失败,也不会去尝试切换,这个和超时不是一个概念
<dubbo:reference id="demoService" interface="com.mor.server.dubbo.service.DemoServer" cluster="failover" retries="2"/>
- Forking 并行调用多个服务器,只要一个成功即返回。(会导致重复写)
通常用于实时性要求较高的读操作,但需要浪费更多服务资源
failfast 快速失效
只发起一次调用,失败立即报错。通常用于非幂等性写操作,比如说新增记录。
但是这里也会有问题的,如果是因为网络问题,Provider的响应时间慢,Consumer以为调用失败了,但是Provider却调用成功了,涉及到分布式事务的问题。
如果是因为Provider报错的话,倒没事,因为两边都显示执行失败。failback:调用失败后,consumer不会重试,而是把这个消息丢到provider的重试的线程池里面,定时的重试调用一定的次数,调用失败写日志
Failsafe:调用失败不重试,不报错,返回一个空的结果,输出日志
Broadcast:轮询调用所有的 provider,只要有1个失败,最终就会抛出异常
Dubbo 并发控制
http://ifeve.com/dubbo-para-control/
- 在客户端控制调用并发数
- Provider控制最大连接数
- 设置Dubbo Provider的请求线程池最大值
客户端并发控制:actives参数
参考源码:ActiveLimitFilter
- 设置UserServiceBo接口中所有方法,每个方法最多同时并发请求10个请求
- 如果客户端请求该方法并发超过了10则客户端会被阻塞(count.wait),等客户端并发请求数量少于10的时候,该请求才会被发送到服务提供方服务器
- 如果等待时间超时,则抛出异常,这时候服务根本都没有发送到服务提供方服务器。
<dubbo:reference interface="com.test.UserServiceBo" actives="10"/>
服务端并发控制:executes参数
- 服务端并发执行(或占用线程池线程数)不能超过10个,超过的话,直接报错
- 源码参考ExecuteLimitFilter
- 设置dubbo协议的时候,支持设置最大长连接数(不同于并发执行数)
<dubbo:service interface="com.foo.BarService" executes="10" />
<dubbo:protocol name="dubbo" accepts="1000" />
Dubbo线程池
https://www.cnblogs.com/killbug/p/7588877.html
- Dubbo不同于RocketMQ,没有中介堆积调用,但是Dubbo有线程池可以缓冲调用。Dubbo支持3种线程池,并且在流量过大的时候,直接丢弃新增的请求,并且抛出异常
- 可以指定最大线程池的数量,配置方式如下
<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />
三种线程池:
- fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省),超过设定的threads,直接丢弃请求且报错
new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(queues)),new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
- cached 缓存线程池,空闲一分钟自动删除,需要时重建。
- limited 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。