Dubbo的9种集群容错方案的总结

容错机制的研究

本文最好结合 https://github.com/apache/dubbo 源码理解。

找到 AbstractClusterInvoker 的所有子类,他们的集群容错功能都在 AbstractClusterInvoker.doInvoker()实现。

在此之前最好理解:

[集群 cluster]
https://zh.wikipedia.org/wiki/%E8%AE%A1%E7%AE%97%E6%9C%BA%E9%9B%86%E7%BE%A4

[容错 ]
https://zh.wikipedia.org/wiki/%E6%95%85%E9%9A%9C%E5%AE%B9%E8%A8%B1%E5%BA%A6

[目录]
https://zh.wikipedia.org/wiki/%E7%9B%AE%E5%BD%95%E6%9C%8D%E5%8A%A1

[节点]
dubbo节点包括,directory,monitor,invoker,registry 四类的概念

一、 通俗解释

容错就是当我们在进行函数调用过程中被调用者出现故障时承诺的补偿处理方案。

二、具体方案


1).故障转移 Fail Over

- 处理方案

通过负载均衡重新选一台Provider提供服务。

- 特点

需要处理等幂性,Loadbalance。会一直转移直到碰到对的provider。会拉长响应时间。


2).快速失败 Fast Fail

- 处理方案

出错直接返回

- 特点

等于放弃做容错了,直接抛出异常,让业务端自己处理问题。也会做Loadbalance。


3).忽略错误 Fail Safe (佛系处理)

- 处理方案

直接忽略错误,返回一个null值,并记录日志。

- 特点

等于没有异常了,服务提供者要么返回空值,要么返回正确值。可以理解为是一种特殊快速失败法。


4).异步重试 Fail Back (死信队列重试)

- 处理方案

异常,则启动定时任务进行重试,直到重试指定次数后异步返回或者输出log宣告失败。

- 特点

loadbalance,会重试n次,需要等幂处理,由于调用过的provider可能会被重新调用(巨坑),所以当provider大面积不可用容易引发雪崩,雪崩的原因为 调用过的provider可能会被重新调用


5).并行调用 Fork

- 处理方案3

用线程池调用指定个数的provider,只要有一个返回就推出,不管返回的是否为异常。

- 特点

可以利用集群提高响应性能,不算容错,这个性能提升代价,就是要用到线程池。
花里花俏,没有想到合适应用场景。


6).广播调用 Broadcast

- 处理方案

所有provider都会被同步调用一遍,如果发送异常,则只是简单log。等同步调用完毕后, 只要有一个发送异常,最后会抛出异常,如果全部没有异常,则返回最后一个provider的result.

- 特点

适合用来做consumer推送通知给Provider集群,我们通过返回值可以判断是否有接收者异常,还说说全都成功了。


7).伪造返回 Mock

实现类,他有点特殊,他不是集群级别的容错,他只是接口级别的容错。所以不属于 AbstractClusterInvoker 的子类。

public class MockClusterInvoker implements Invoker

- 处理方案

可以用来做服务降级,当发送故障时自动调用mockInvoker接口,也可以人工到monitor后台去强制force.mock实现主动屏蔽provider列表。服务降级可以作为容错的兜底方案,当容错解决不了问题,就用降级做兜底。

- 特点

不属于集群容错,作为容错失效的兜底方案,可以人工在monitor后台对服务接口进行force.mock屏蔽。


8).遍历找到可用的为止 Available

- 处理方案

算是非负载均衡版本的故障转移,他会遍历所有Invoker节点(dubbo节点包括,directory,monitor,invoker,registry),然后调用Node.isAvailable函数。每个Node都会实现自己的isAvailable函数,用来告诉调用者节点是否有效,比如,有点通过套接字是否关闭,有的判断destroy()函数是否被调用。

- 特点

涉及到了Node的概念和Node.isAvailable()概念,其原理很简单就是robin.


9).合并请求 Mergeable

- 处理方案

如果有指定merger的话,合并所有请求的非异常结果。如果没有则会robin,找一个有效结果执行返回而已。

- 特点

适合用来对所有provider数据做采集。这个方法会使用反射机制自己组合返回结果列表。调用起来相对慢。


总结:

  • 负载均衡未必是好事,他会使得请求变得难以跟踪。一些类似 Available这种遍历的方法,反而有利于我们跟踪调用链路和简单定位错误。

  • 故障转移的方式有很多种,他们都有一个缺点,得处理等幂问题。

  • 抛出异常是最直接的手段,即把问题交给客户端,但是这显得很不负责人。而容错机制就是提客户端做决定。这种人性化的决定是有代价的,那就是增大延迟(降低了响应速度)。

  • 所有具有容错功能的Invoker节点都是 AbstractClusterInvoker 的子类,他们的集群容错功能都在 AbstractClusterInvoker.doInvoker()可以找到。

关键词:

负载均衡,定位故障
故障转移,等幂处理,
替客户端做决定, 响应变慢

你可能感兴趣的:(dubbo)