本文聊聊 dubbo 的最核心模型 Invoker,在 dubbo 官网上是这么描述的:

Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠拢,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

Invoker 是一个执行体的抽象,执行体可以是本地的也可以是远程的,可以是集群的也可以是单实例的,可以是真实的业务实现也可以是伪装的本地实现,可以是 dubbo协议也可以是其他协议,他的抽象等级非常高,不关心具体实现只关心输入和输出。

先看下 Invoker 的接口声明:

public interface Invoker<T> extends Node {

    // 这个 Invoker 可执行体是承载的那个接口,如 DemoService
    Class<T> getInterface();
    // 最核心的调用模型,传入一个 Invocation 会话域返回一个带有结果的实体
    Result invoke(Invocation invocation) throws RpcException;
}

另一个核心模型 Protocol 负责管理 Invoker 的生命周期,它的 API 都是围绕着 Invoker 进行的,看看它的接口声明:

public interface Protocol {
    // 服务端暴露端口
    int getDefaultPort();
    // 服务端暴露方式
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
    // 客户端引用方式
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
    // 销毁方式,服务端、客户端都使用
    void destroy();
}

Invoker 是dubbo的灵魂,服务端和客户端都是围绕这个实体来运转,不同的 Invoker 承载不同的调用方式。

从他们的使用场景来看可以分为以下几类:

  • 服务端代理类

其实现类主要以 AbstractProxyInvoker 为父类,主要有:

Anonymous in getInvoker() in JavassistProxyFactory 
Anonymous in getInvoker() in JdkProxyFactory 
ByteBuddyProxyInvoker // 3.x 新增

他们的主要作用是在服务端将远程调用关联到本地具体的执行业务方法上,也就是本地业务接口的代理,这也是它命名为 proxyInvoker 的原因,由于框架本身无法事先知道业务接口所以这里将业务接口用字节码编译技术用 Wrapper 进行包装,最后通过 Wrapper#invokeMethod 调用真实的实现。

这里以源码demo中的 DemoService 实现类为例看下生成的的invokeMethod实现:

public class Wrapper0 extends Wrapper implements ClassGenerator.DC {
    public Object invokeMethod(Object var1, String var2, Class[] var3, Object[] var4) throws InvocationTargetException {
        DemoService var5;
        try {
            var5 = (DemoService) var1;
        } catch (Throwable var8) {
            throw new IllegalArgumentException(var8);
        }
        try {
            // 根据接口和方法名找到对应的业务实现进行真实调用
            if ("sayHello".equals(var2) && var3.length == 1) {
                return var5.sayHello((String) var4[0]);
            }
        } catch (Throwable var9) {
            throw new InvocationTargetException(var9);
        }
        throw new NoSuchMethodException("Not found method \"" + var2 + "\" in class com.alibaba.dubbo.demo.DemoService.");
    }
}

在服务端生成 Wrapper 类后框架层不会直接调用业务实现类,而是通过 Wrapper 类委托给真实的实现类,这样就实现了和业务解耦。

  • 单个实例远程调用类

这些类大都以 AbstractInvoker 为基类,主要包括以下几个:

Anonymous in refer() in MemcachedProtocol 
Anonymous in refer() in RedisProtocol 
DubboInvoker 
InjvmInvoker 
ThriftInvoker 
GrpcInvoker 2.7.x 新增
TripleInvoker 3.x 新增
MockInvoker  未继承 AbstractInvoker

这些大都是具体的协议的远程调用的实现,也就是 Protocol#refer 出来的对象,只针对单个服务端实例,集群模式下再使用集群 ClusterInvoker 进行增强。
其内部实现大都是通过通过 socket 链接将本地调用进行编码发送到远程,典型如 DubboInvoker,也有特殊的如 InjvmInvoker 是 jvm 内本地直接调用而不用通过 socket。

MockInvoker 是一个比较特殊的实现,它并不和某个协议捆绑,他主要用来实现本地伪装,主要在 MockClusterInvoker 中和服务降级一起使用。

  • 集群远程调用类

这些类大都以 AbstractClusterInvoker 为基类,3.x后增加了接口 ClusterInvoker,主要包括以下几个:

Anonymous in join() in AvailableCluster 
AvailableClusterInvoker 
BroadcastClusterInvoker 
FailbackClusterInvoker 
FailfastClusterInvoker 
FailoverClusterInvoker 
FailsafeClusterInvoker 
ForkingClusterInvoker 
ZoneAwareClusterInvoker 2.7.x 新增
MergeableClusterInvoker 
MockClusterInvoker  未继承 AbstractClusterInvoker

这些类正常情况下并不真正进行远程调用逻辑,他们都是将多个远程单实例调用类进行聚合增强来实现不同的集群容错逻辑,底层还是委托给 AbstractInvoker 的那些实现,负载均衡策略也是在这个层面实现的。

MockClusterInvoker 是一个比较特殊的类,默认情况下其他的 ClusterInvoker 都会被包裹在 MockClusterInvoker 中进行增强实现服务降级和本地伪装。

  • 本地增强类,过滤器

这些类没有通用逻辑,他们大都是单一的功能增强实现。

Anonymous in buildInvokerChain() in ProtocolFilterWrapper 
ConsumerInvokerWrapper 
DelegateInvoker 
DelegateProviderMetaDataInvoker 
ListenerInvokerWrapper 
ProviderInvokerWrapper 

Anonymous in buildInvokerChain() in ProtocolFilterWrapper 主要实现了过滤器逻辑,它将各个 Filter 转换为一个 Invoker 链表,以此实现过滤器串行可阻断的调用,后来的 dubbo 中增加了异步过滤器其实现就更加复杂了些,用 CopyOfFilterChainNode 进行代替,此处不再赘述。

其他的几个增强类都比较简单,不再一一介绍,有兴趣的可以翻翻源码,逻辑很简单。


Foghost
58 声望0 粉丝