Dubbo—SPI及自适应扩展原理

推荐学习

  • 开心到飞起!Alibaba百万年薪必备—高性能架构路线已到手
  • 被微服务轰炸?莫怕!耗时35天整出的「微服务学习教程」送你
引言Dubbo虽然已交由apache管理 , 并且社区活跃度也不如SpringCloud , 但也是国内应用比较广泛的RPC框架 , 其背后的设计思想非常值得我们学习借鉴 。 鉴于Dubbo官方文档对于基础的使用配置已经讲解的非常清楚了 , 这里就不再赘述 。 本文章将基于Dubbo2.5.3版本的源码做分析 。 而Dubbo中最核心的一点就是SPI和自适应扩展 , Dubbo的高扩展性以及其它功能都是在这个基础上实现的 , 理解掌握其原理才能看懂后面的一系列功能的实现原理 , 对我们平时实现高扩展性也非常有帮助 。 (PS:Dubbo源码不像Zookeeper那样有明确的入口 , 可以根据官网的源码分析指导找到 。 )
Dubbo—SPI及自适应扩展原理文章插图
正文一、什么是SPI?SPI(Service Provider Interface)是一种服务发现机制 , 它的作用是解耦接口和其具体实现 , 让各厂商可以自定义自己的扩展实现 , 并使得程序可以自动使用引入的组件 。 什么意思呢?举个例子就清楚了 , Java原生就提供SPI机制 , 比如数据库连接驱动的实现就是SPI很好的一个应用 , 在Java sql下提供了Driver接口 , 而具体的驱动程序是由各个数据库厂商实现的 , 平时我们要连接哪个数据库只需要引入对应的驱动jar包就可以了 , 非常方便 , 即使数据库变更也一样 , 我们不需要改变代码 。 而Dubbo的SPI机制则是在此基础上提供了更强大的功能 , 因此 , 学习了解Java SPI更益于深入了解Dubbo , 下面就先来看看Java SPI的使用吧 。
1. Java SPI的实现
  • 首先定义一个服务接口和两个自定义实现类(一般实现类会由第三方提供):
public interface SPI {void sayHello(String s);}public class SPIImpl1 implements SPI {@Overridepublic void sayHello(String s) {System.out.println("Hello, " + s + "! I'm one");}}public class SPIImpl2 implements SPI {@Overridepublic void sayHello(String s) {System.out.println("Hello, " + s + "! I'm two");}}
  • 然后在resources/META-INF/services创建一个以接口全类名为名称的文件cn.dark.SPI , 并在文件中填入自定义实现类的全类名
cn.dark.SPIImpl1cn.dark.SPIImpl2
  • 最后通过ServiceLoader类发现并调用服务:
ServiceLoader load = ServiceLoader.load(SPI.class);for (SPI spi : load) {spi.sayHello("SPI");}输出:
Hello, SPI! I'm oneHello, SPI! I'm two如果需要扩展新的实现 , 只需要将实现类配置到资源文件中 , 并引入对应的Jar即可 。 Java SPI机制就这么简单 , 其实现原理也很简单 , 读者们可以自行阅读源码 , 这里就不再详细分析了 , 那Dubbo的SPI有何异同呢?
2. Dubbo SPI实现原理由配置文件得到的猜想Dubbo SPI是基于Java原生SPI思想重新实现的一套更加强大的SPI机制 , 类似的你可以在Dubbo的META-INF.dubbo.internal(不止这一个路径 , 后面在源码中会看到)路径下看到很多以接口全类名命名的配置文件 , 但是文件内容和JAVA SPI有点不一样 , 以Protocol扩展为例:
registry=com.alibaba.dubbo.registry.integration.RegistryProtocolfilter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapperlistener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrappermock=com.alibaba.dubbo.rpc.support.MockProtocolinjvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocoldubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocolrmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocolhessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocolcom.alibaba.dubbo.rpc.protocol.http.HttpProtocolcom.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocolthrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocolmemcached=memcom.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocolredis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol