Dubbo 源码分析 - Dubbo SPI 在 Protocol 层 的应用

开篇

前面通过三篇文章讲述了 Dubbo SPI 的其中三种用法:

本文通过 Dubbo 的一个应用案例 - 获取 Protocol 扩展实例, 来看看 Dubbo SPI 在源码中的具体应用实现.

阅读本文之前,请结合上述文章 或者 官网 Dubbo SPI,或者其他相关文章, 对 Dubbo SPI 有一定程度的了解.

正文

通过 Dubbo 官方文档-框架设计篇, 可以看出 Dubbo 整体被分为 十 层, 其中 Service 和 Config 层为 API,其它各层均为 SPI, 也就是说其他各层都有对应的多个扩展实现.

比如协议层 Protocol 的已知扩展:

  • org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol
  • org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
  • org.apache.dubbo.rpc.protocol.rmi.RmiProtocol
  • org.apache.dubbo.rpc.protocol.http.HttpProtocol
  • org.apache.dubbo.rpc.protocol.http.hessian.HessianProtocol

本文就 Protocol 扩展点来看下 Dubbo 是如何应用的.

Protocol 扩展点

如下所示, 为 Protocol 的部分源码,

@SPI("dubbo")
public interface Protocol {

	// 省略其他代码
	
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
}

根据我们之前讲的 Dubbo SPI 的使用方法, 我们可以得出以下几个结论:

  • SPI 注解 value 值为 dubbo, 也就是 Protocol 层默认使用的是 Dubbo 协议
  • export 方法上的 @Adaptive注解表明该方法作为一个自适应扩展点, 也就是会动态生成一个 Protocol$Adaptive 实例

部分代码如下所示, 完整版请到 Dubbo SPI 使用方法(二)- 扩展点自适应 文章末尾

public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {

    public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
      // 省略部分代码
    }
}

接下来, 通过 Dubbo 的服务暴露流程看下 Protocol 扩展的具体应用.

服务暴露流程

因为 Dubbo(2.7.x) 本身支持很多协议,以及暴露方式, 而以下分析的内容或者流程都是基于:

将一个服务注册到 zookeeper 中, 进行远程暴露(dubbo 协议),

远程服务暴露流程(粗略版)

这是服务暴露的一个大概的时序图, 详细的后面会继续讨论,

  • 先经过 RegisterProtocol
  • 再经过 DubboProtocol
    在这里插入图片描述
    从上面的时序图中可以看出:
  1. 在 ServiceConfig 的 doExportUrlsFor1Protocol方法中调用 Protocol 的 export方法
private void doExportUrlsFor1Protocol() {
    // 省略一堆流程
	Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
}

而我们的 PROTOCOL 定义如下:

private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

因此我们可以得知, 这里获取的是一个自适应扩展实例, 因为 URL 参数中携带协议是 registry,所以先获得的是上面时序图中提到的 RegisterProtocol, 处理完后,才是 DubboProtocol.

除此之外, 根据我们之前讲过的 Dubbo SPI 的另一种使用方法: 扩展点自动包装 , 我们可以看到 Protocol 定义了如下 Wrapper:

qos=org.apache.dubbo.qos.protocol.QosProtocolWrapper
filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
远程服务暴露流程(略详细版)

结合上面的内容, 我们对上面的时序图做一个较详细的补充:
每次通过 Protocol 获取扩展实例时, 都会依次经过 Protocol$Adaptive, QosProtocolWrapper, ProtocolListenerWrapper, ProtocolFilterWrapper, 最终才会调用目标实例 RegisterProtocol 或者 DubboProtocol
在这里插入图片描述

在这里插入图片描述

总结

Dubbo 优秀的原因之一在于它的扩展性非常强, 而这种特性是基于 SPI 扩展接口实现的.

Dubbo SPI 是对 JDK SPI 的一种增强实现, 其中包括:

  • 通过 @Adaptive注解实现扩展点自适应
  • 对扩展接口的 IOC(使用 set 方法注入其他扩展接口)
  • 对 AOP 的支持 (使用 Wrapper 类对扩展接口的功能进行增强)
  • 其他

本文对 Dubbo 的 Protocol 层的扩展讨论, 就有涉及到上述的使用方法, 因此才出现了在 ServiceConfig 中调用 Protocol#export方法, 会经过多个 Protocol 的实现.

同时也说明了一点, 要想搞懂 Dubbo 的源码, 必须对其扩展机制有一定的认知.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值