上图是Dubbo官网基于Dubbo 3的服务调用链路,从服务消费端发起请求,到服务提供端接收请求,Dubbo 在整个设计中提供了很多扩展点,其中最常用的包括ClusterFilter、Router、LoadBalance、Filter等。
Cluster
远程调用,不可避免会遇到各种各样的问题而导致调用失败,比如网络异常、服务端故障。而当服务调用失败后,服务消费端需要采用一定的应对策略。在Dubbo中提供有如下所示的服务容错策略。
FailoverCluster:失败重试,调用失败后,重试调用另一个服务提供者FailfastCluster:快速失败,调用失败后,立即抛出异常FailsafeCluster:失败安全,调用失败后,不抛异常,返回一个空结果FailbackCluster:失败自动恢复,调用失败后,定时补偿调用ForkingCluster:并行调用多个服务提供者,获取最先成功的调用结果
Router
通过 Router 路由规则可以过滤出用于远程调用的Invoker集合,通常可以借用 Router 来实现灰度发布 或 多泳道的环境路由。Dubbo 通过SPI机制以及@Activate来确定使用哪些路由。通过@Activate来确定激活哪些RouterFactory,然后再通过RouterFactory创建Router对象,最后通过Router.route()来过滤Invoker。
LoadBalance
通过Router过滤出远程调用的Invoker集合后,Dubbo 使用LoadBalance确定具体的一个Invoker,执行远程调用。
Dubbo 默认提供的负载均衡机制如下:
RandomLoadBalance: 根据服务权重随机分配
RoundRobinLoadBalance: 加权轮询
ConsistentHashLoadBalance: 一致性哈希
LeastActiveLoadBalance: 最小活跃数算法
同样我们可以自己扩展LoadBalance
-
继承
AbstractLoadBalance,自定义LoadBalance,实现方法doSelect() -
src/main/resources/META-INF/dubbo下创建org.apache.dubbo.rpc.cluster.LoadBalance文件,定义我们自己写的LoadBalancepublic class SimpleLoadBalance extends AbstractLoadBalance { @Override protected Invoker doSelect(List<Invoker> invokers, URL url, Invocation invocation) { // 自定义负载均衡算法 return invokers.get(0); } }
Filter
同 Servlet 的 Filter一样,Dubbo 也有自己的过滤器链,我们可以通过扩展 Filter 来做一些通用处理,比如鉴权、日志记录、限流操作等。
-
实现org.apache.dubbo.rpc.Filter
@Activate(group = PROVIDER) public class AuthFilter implements Filter { @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { // TODO 鉴权操作 or 日志记录等
return invoker.invoke(invocation); }}
-
src/main/resources/META-INF/dubbo/下创建org.apache.dubbo.rpc.Filter文件 -
这里采用了 @Activate 注解自动激活,所以会自动执行此过滤器
小结
总结一下从消费方发起调用到服务端接收请求,链路如下:
服务消费方:
- 封装
Invocation对象 - 将
Invocation对象传递给ClusterFilter做选址前的请求预处理,如请求参数的转换、请求日志记录、限流等 - 将
Invocation对象传递给Cluster进行集群调用,在调用出错后可以执行对应的策略-
Cluster创建ClusterInvoker -
ClusterInvoker调用Directory获取所有可用的服务端地址 -
Directory调用StateRouter和Router对服务端的地址信息进行路由,比如做灰度或多泳道配置,可以基于Router来实现 -
Cluster获得可用的服务端地址后,通过LoadBalance来实现负载均衡
-
- 获取服务提供者的具体
Invoker,通过Filter过滤器进行请求前的处理 - 将
Invocation对象网络传输到服务提供端
服务提供端:
- 服务端首先构建
Invocation对象 - 然后会经过
Filter过滤器,做请求的预处理,如鉴权、日志记录、限流等 - 动态代理调用实现