Dubbo Cluster集群那点你不知道的事。 (下)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Dubbo Cluster集群那点你不知道的事。 (下)

FailoverCluster doInvoke源码解析


接下来我们就对FailoverClusterInvoker的doInvoke方法的源码进行解析。


这一小节主要回答这一个问题:Failover Cluster调用失败之后,会自动切换Invoker进行几次重试呢?


通过源码,我们可以知道默认的重试次数是2次


有人就问了:为什么第61行的最后还有一个"+1"呢?


你想一想。我们想要在接口调用失败后,重试n次,这个n就是DEFAULT_RETRIES,默认为2。那么我们总的调用次数就是n+1次了。所以这个"+1"是这样来的,很小的一个点。

另外图中标记了红色五角星★的地方,第62到64行。也是很关键的地方。对于retries参数,在官网上的描述是这样的:


不需要重试请设为0。我们前面分析了,当设置为0的时候,只会调用一次。

但是我也看见过retries配置为"-1"的。-1+1=0。调用0次明显是一个错误的含义。但是程序也正常运行,且只调用一次。


这就是标记了红色五角星★的地方的功劳了。防御性编程。哪怕你设置为-10086也只会调用一次。


接下来对doInvoke方法进行一个全面的解读,下面是2.7.5版本的源码,我基本上每一行主要的代码都加了注释,可以点开大图查看: org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke


如上所示,FailoverClusterInvoker的doInvoke方法主要的工作流程是:

首先是获取重试次数,然后根据重试次数进行循环调用,在循环体内,如果失败,则进行重试。


在循环体内,首先是调用父类AbstractClusterInvoker的select方法,通过负载均衡组件选择一个Invoker,然后再通过这个Invoker的invoke方法进行远程调用。如果失败了,记录下异常,并进行重试。


注意一个细节:在进行重试前,重新获取最新的invoker集合,这样做的好处是,如果在重试的过程中某个服务挂了,可以通过调用list方法可以保证copyInvokers是最新的可用的invoker列表。


整个流程大致如此,不是很难理解。


什么是Dubbo的粘滞连接?


接下来我们要看的是父类AbstractClusterInvoker的select方法的逻辑。但是在看select方法的逻辑之前,我必须得先铺垫一下Dubbo粘滞连接特性的知识。

官网上的解释是这样的:


可以看出,这是一个服务治理类型的参数。当设置true时,该接口上的所有方法使用同一个provider。官方文档中说明可以用在接口和方法级别。


这些都是一些比较简单的服务治理的规则。如果需求更复杂,则需要使用路由功能。

官方文档已经说的很清楚了。我就只简单的解释一下第一句话:粘滞连接用于有状态服务。


那么什么是有状态服务,什么又是无状态服务呢?


根据我简单的理解。对服务提供者来说,究竟是有状态的服务提供者,还是无状态服务,其判断依据就一句话: 从客户端发起的两个或者多个请求,在服务端是否具备上下文关系。


举个例子,我们经常会用到的session。


众所周知,HTTP协议是无状态的。那么当在一个电商场景下,将用户挑选的商品放到购物车,保存到session里,当付款的时候,再从购物车里取出商品信息。这样通过session就实现了有状态的服务。


当一个服务被设计为无状态的时候,对于客户端来说,可以随意调用。所以无状态的服务可以很容易的进行水平扩容。


当一个服务被设计为有状态的时候,想要水平扩容的时候就不是那么简单了。因为客户端和服务端存在着上下文关系,所以客户端每次都需要请求那一台服务端。


把一个有状态的服务修改为无状态的服务的方案也很简单。还是拿session举例,这个时候,我们的分布式session就呼之欲出了。把session集中存储起来,比如放到redis中,弄一个独立于服务的session共享层。这样,一个有状态的服务就可以变为一个无状态的服务


AbstractClusterInvoker select源码解析


看完这一小节,你也就知道了粘滞连接在Cluster中是怎么应用的了。


有了粘滞连接的知识储备后,再看select方法就比较轻松了,首先需要知道的是select方法是一个关键的公共方法,其作用就是选择出一个可用的invoke,有下面这几个Cluster的实现类都在调用:


代码片段不长,逻辑也比较清楚,具体代码解析如下:


根据代码画出select方法的流程图如下:



结合代码和流程图,再进行一个文字描述。

先介绍一下select的四个入参,分别是:


loanbalance:负载均衡策略。


invocation:它持有调用过程中的变量,比如方法名,参数等。


invokers:这里的invokers列表可以看做是存活着的服务提供者列表。


selected:已经被选择过的invoker集合。


通过源码我们可以看出,select方法的主要逻辑集中在了对粘滞连接特性的支持上。


首先是获取sticky配置,然后再检测invokers列表中是否包含 stickyInvoker,如果不包含,则认为该stickyInvoker不可用,此时将其置空。

为什么可以置空?


因为这里的invokers列表是存活着的服务提供者列表,如果这个列表不包含stickyInvoker,那自然而然的认为stickyInvoker挂了,所以置空。


接下来,如果stickyInvoker存在于invokers列表中,说明stickyInvoker还活着,此时要进行下一项检测。检测selected(选择过的服务提供者列表)中是否包含 stickyInvoker。


如果包含的话,说明stickyInvoker在此之前没有成功提供服务(但其仍然处于存活状态)。此时我们认为这个服务不可靠,不应该在重试期间内再次被调用,因此这个时候不会返回该stickyInvoker。


如果selected不包含stickyInvoker,此时还需要进行可用性检测,比如检测服务提供者网络连通性等。当可用性检测通过,才可返回 stickyInvoker,否则调用doSelect方法选择Invoker。


如果sticky为true,此时会将doSelect方法选出的Invoker赋值给stickyInvoker。

关于粘滞连接和可用性检测的默认配置如下:


即默认情况下粘滞连接是关闭状态。当粘滞连接开启时,默认会进行可用性检查。

关于select方法先分析这么多,继续向下分析。


AbstractClusterInvoker doSelect源码解析


读完这一小节你可以回答出这两个问题:


1.Cluster选择出一个可用的Invoker最多要进行几次选择?


2.请问几次选择分别是什么?


doSelect方法的源码解析如下:



Failover Cluster选择出一个可用的Invoker最多要进行三次选择,也是doSelect的主要逻辑,三次分别是(图中标号了①②③的地方):


①:通过负载均衡组件选择 Invoker。


②:如果选出来的 Invoker 不稳定,或不可用,此时需要调用reselect 方法进行重选。


③:reselect选出来的Invoker为空,此时定位invoker在invokers列表中的位置index,然后获取index+1处的 invoker。


AbstractClusterInvoker reselect源码解析


下面我们来看一下 reselect 方法的逻辑。



根据源码做出流程图如下:


所以,reselect方法总结下来其实做了四件事情:


第一:查找可用的invoker,并将其添加到reselectInvokers集合中。这个reselectInvokers集合你可以理解为里面放的是所有的可用的invoker的集合与selected集合的差集。


第二:如果经过筛选后,reselectInvokers不为空,则通过负载均衡组件再次进行选择并返回。


第三:如果经过筛选后,reselectInvokers为空,则再从selected集合(已经被调用过的集合)中选出所有可用的invoker,放到reselectInvokers中,再次通过负载均衡组件进行选择并返回。


第四:如果进过上面的步骤后,没有选择出合适的invoker,reselectInvokers还是为空,说明所有的invoker都不可用了,返回为null。

好了,到这里就把最开始抛出的8个问题都解答完毕了,接下来对问题、答案进行一个汇总。


问题、答案汇总


1.Dubbo Cluster集群的作用是什么?

简单来说:集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以专心处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等。这就是Dubbo Cluster集群的作用。


2.Dubbo Cluster的10个实现类你能说出来几个,其中哪几个是集群容错的方法实现?

根据配置可以知道Dubbo集群接口Cluster有10种实现方法如下:


其中failover、failfast、failsafe、failback、forking、broadcast这6种才属于集群容错的范畴。另外的实现均有其他的应用场景。还需要注意的是zone-aware是2.7.5版本后才支持的实现类,之前是registryaware。


3.默认的集群实现类是什么呢?

失败自动切换: org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker


4.Failover Cluster调用失败之后,会自动切换Invoker进行几次重试呢?

自动进行2次重试,共计调用3次。


5.什么是Dubbo的粘滞连接?

粘滞连接用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非该提供者挂了,再连另一台。粘滞连接将自动开启延迟连接,以减少长连接数。


6.粘滞连接在Cluster中是怎么应用的?

参照AbstractClusterInvoker select源码解析。select方法的主要逻辑集中在了对粘滞连接特性的支持上。


7.Cluster选择出一个可用的Invoker最多要进行几次选择?

最多进行三次选择。


8.请问几次选择分别是什么?

①:通过负载均衡组件选择 Invoker。 ②:如果选出来的 Invoker 不稳定,或不可用,此时需要调用reselect 方法进行重选。 ③:reselect选出来的Invoker为空,此时定位invoker在invokers列表中的位置index,然后获取index+1处的 invoker。


最后说一句(求个关注)


之前也写过几篇Dubbo相关的文章,有兴趣的可以看一看:


《Dubbo 2.7.5在线程模型上的优化》

《快速失败机制&失败安全机制》

《够强!一行代码就修复了我提的Dubbo的Bug。》

《Dubbo加权轮询负载均衡的源码和Bug,了解一下?》

《Dubbo一致性哈希负载均衡的源码和Bug,了解一下?》

《一文讲透Dubbo负载均衡之最小活跃数算法》

《参加Dubbo社区开发者日成都站后,带给我的一点思考。》

《Dubbo 2.7新特性之异步化改造》

才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。


感谢您的阅读,原创不易,求个关注.

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
3月前
|
缓存 负载均衡 Dubbo
Dubbo服务集群容错原理(重要)
该文章主要介绍了Dubbo服务集群容错的原理,包括集群容错技术的概念、Dubbo中使用的集群容错技术种类及其原理。
|
消息中间件 运维 负载均衡
Dubbo负载均衡和集群容错和动态代理策略
Dubbo负载均衡和集群容错和动态代理策略
123 0
|
监控 Dubbo 应用服务中间件
Dubbo预备知识集群和分布式
Dubbo预备知识集群和分布式
39 0
|
存储 Prometheus 监控
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(1)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(1)
137 6
|
Prometheus 监控 Dubbo
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(5)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(5)
112 4
|
监控 Dubbo 数据可视化
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(3)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(3)
167 5
|
Prometheus 监控 Dubbo
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(6)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(6)
149 1
|
存储 监控 算法
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(4)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(4)
169 4
|
监控 数据可视化 Dubbo
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(7)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(7)
113 2
|
存储 监控 Dubbo
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(2)
带你读《Apache Dubbo微服务开发从入门到精通》——二、 微服务集群监控(2)
113 3