【Dubbo笔记】之 调用链路扩展点梳理

219 阅读3分钟

上图是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

  1. 继承AbstractLoadBalance,自定义LoadBalance,实现方法doSelect()

  2. src/main/resources/META-INF/dubbo下创建org.apache.dubbo.rpc.cluster.LoadBalance文件,定义我们自己写的LoadBalance

    public 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 过滤器,做请求的预处理,如鉴权、日志记录、限流等
  • 动态代理调用实现