概述
近期从不同渠道了解到了一些中间件相关的新的知识,记录一下收获。涉及到的中间件包括RPC调用、动态配置中心、MQ、缓存、数据库、限流等,通过对比加深理解,方便实际应用时候更明确如何进行设计和技术选型。
一、RPC框架中间件系列
1、选型对比相关
目前主流的RPC中间件包括Dubbo、HSF、Thrift、GRPC、Spring Cloud等。结合自己的具体场景选择合适的框架。从性能、通信方式、序列化、语言、易用性、生态等方面对比分析如下:
2、Dubbo中比较核心的SPI的概念
SPI(Service Provider Interface),本质原理—-策略模式+配置+反射:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。我们需要搞清楚java的SPI和Dubbo的SPI区别:
java的SPI:
基本原理:Java的SPI|用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。
实现过程:需要在 classpath 下创建一个目录,该目录命名必须是:META-INF/service2)在该目录下创建一个 文本文件,该文件需要满足以下几个条件文件名必须是扩展的接口的全路径名称文件内部描述的是该扩展接口的所有实现类文件的编码格式是 UTF-83)通过 java.util.ServiceLoader 的加载机制来加载服务。
工作流程:1)当调用 ServiceLoader.load(Class clz) 方法时,会到jar中中的目录 “META-INF/services/“ + clz.getName 进行文件读取,2)当在调用ServiceLoader.forEach()方法时,实际走的是LazyIterator,当在调用LazyIterator.hasNext() 时,在文件中读取到实际的服务实现类并把它们通过调用 Class.forName(String name, boolean initialize,ClassLoader loader)。
应用:javaSPI我们最熟悉的应用就是数据库驱动了,mysql和oracle驱动针对JDBC分别有自己的实现,这就有赖于java的SPI机制。
Dubbo的SPI:
基本原理:在dubbo中也有SPI机制,虽然都需要将接口全限定名配置在文件中,但是dubbo并没有使用java的spi机制,而是重新实现了一套功能更强的 SPI 机制, 支持了AOP与依赖注入,并且 利用缓存提高加载实现类的性能,同时 支持实现类的灵活获取。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。例如dubbo当中的protocol,LoadBalance等都是通过SPI机制扩展。
实现过程:1)需要在 classpath 下创建一个目录,该目录命名可以是:META-INF/service/、META-INF/dubbo/、META-INF/dubbo/internal/2)在该目录下创建一个 文本文件,该文件需要满足以下几个条件文件名必须是扩展的接口的全路径名称文件内部描述的是该扩展接口的所有实现类,将服务实现类写成KV键值对的形式,Key是拓展类的name,Value是扩展的全限定名实现类。3)通过 org.apache.dubbo.common.extension.ExtensionLoader 的加载机制来加载服务
工作流程:两次SPI过程 1)我们首先通过 ExtensionLoader的 getExtensionLoader 方法获取一个接口的 ExtensionLoader 实例,然后再通过 ExtensionLoader 的 getExtension 方法获取拓展类对象 2)通过 ExtensionLoader.getExtensionLoader取到接口的加载器Loader之后,再通过 getExtension方法获取需要拓展类对象。
补充几个核心机制:服务发现机制 SPI、自适应机制 Adaptive、包装机制 Wrapper 与激活机制 Activate;参考https://juejin.cn/post/7112764945120362526?searchId=202401142324596D6049137EA11C7B3412
应用:例如dubbo的多协议的实现等。
区别点:
(1)Java SPI在加载扩展点的时候,会一次性加载所有可用的扩展点,很多是不需要的,会浪费系统资源。
(2)dubboSPI有选择性地加载所需要的SPI接口。javaSPI配置文件中只是简单的列出了所有的扩展实现,而没有给他们命名。导致在程序中很难去准确的引用它们。而dubboSPI配置文件中以键值对的形式有别名,易于区分。
(3)SPI扩展如果依赖其他的扩展,javaspi做不到自动注入和装配,dubbo可以实现自动注入。
(4)javaSPI不提供类似于Spring的IOC和AOP功能,dubboSPI是支持的