Dubbo源码分析之服务暴露

一、Dubbo服务暴露过程

    下图是Dubbo官网的一个服务提供者暴露服务的主过程:上图是服务提供者暴露服务的主过程:

    首先 ServiceConfig 类拿到对外提供服务的实际类 ref(如:HelloWorldImpl),然后通过 ProxyFactory 类的 getInvoker 方法使用 ref 生成一个 AbstractProxyInvoker 实例,到这一步就完成具体服务到 Invoker 的转化。接下来就是 Invoker 转换到 Exporter 的过程。

Dubbo 处理服务暴露的关键就在 Invoker 转换到 Exporter 的过程,上图中的红色部分。下面我们以 Dubbo 和 RMI 这两种典型协议的实现来进行说明:

Dubbo 的实现

Dubbo 协议的 Invoker 转为 Exporter 发生在 DubboProtocol 类的 export 方法,它主要是打开 socket 侦听服务,并接收客户端发来的各种请求,通讯细节由 Dubbo 自己实现。

RMI 的实现

RMI 协议的 Invoker 转为 Exporter 发生在 RmiProtocol类的 export 方法,它通过 Spring 或 Dubbo 或 JDK 来实现 RMI 服务,通讯细节这一块由 JDK 底层来实现,这就省了不少工作量。

解析服务

在ServiceConfig.export()或ReferenceConfig.get()初始化时,将Bean对象转换暴露服务或请求服务的URL,所有Bean属性转成URL的参数。

然后将URL传给Protocol扩展点,基于扩展点的Adaptive机制,根据URL的协议头,进行不同协议的服务暴露或引用。

url参数列只有group,interface,version是服务的匹配条件,三者决定是不是同一个服务,其它配置项均为调优和治理参数

暴露服务

有注册中心配置:<dubbo:registry address="zookeeper://10.20.153.10:2181" />

ServiceConfig解析出的URL的格式为:

registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")

1)基于扩展点的Adaptive机制,通过URL的"registry://"协议头识别,就会调用RegistryProtocol的export()方法,将export参数中的提供者URL,先注册到注册中心,再重新传给Protocol扩展点进行暴露:

dubbo://service-host/com.foo.FooService?version=1.0.0

2)基于扩展点的Adaptive机制,通过提供者URL的"dubbo://"协议头识别,就会调用DubboProtocol的export()方法,打开服务端口。

Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);

Exporter<?> exporter = protocol.export(invoker);

具体服务àInvoker àExporter  Exporter是负载打开服务端口等待请求。

引用服务

注册中心配置:<dubbo:registry address="zookeeper://10.20.153.10:2181" />

ReferenceConfig解析出的URL的格式为:

registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")

基于扩展点的Adaptive机制,通过URL的"registry://"协议头识别,就会调用RegistryProtocol的refer()方法,基于refer参数中的条件,查询提供者URL,如:

dubbo://service-host/com.foo.FooService?version=1.0.0

基于扩展点的Adaptive机制,通过提供者URL的"dubbo://"协议头识别,就会调用DubboProtocol的refer()方法,得到提供者引用。

然后RegistryProtocol将多个提供者引用,通过Cluster扩展点,伪装成单个提供者引用返回。

invoker = refprotocol.refer(interfaceClass, urls.get(0));

(T) proxyFactory.getProxy(invoker);

拦截服务

基于ProtocolFilterWrapper类,将所有Filter组装成链,在链的最后一节调用真实的引用。

基于ProtocolListenerWrapper类,将所有InvokerListener和ExporterListener组装集合,在暴露和引用前后,进行回调。

包括监控在内,所有附加功能,全部通过Filter拦截实现。

  • 用户自定义filter默认在内置filter之后。
  • 特殊值default,表示缺省扩展点插入的位置。
    • 比如:filter="xxx,default,yyy",表示xxx在缺省filter之前,yyy在缺省filter之后。
  • 特殊符号-,表示剔除。
    • 比如:filter="-foo1",剔除添加缺省扩展点foo1。
    • 比如:filter="-default",剔除添加所有缺省扩展点。
  • provider和service同时配置的filter时,累加所有filter,而不是覆盖。
    • 比如:<dubbo:provider filter="xxx,yyy"/>和<dubbo:service filter="aaa,bbb" />,则xxx,yyy,aaa,bbb均会生效。
    • 如果要覆盖,需配置:<dubbo:service filter="-xxx,-yyy,aaa,bbb" />

猜你喜欢

转载自my.oschina.net/u/3729778/blog/1627657