10分钟带你彻底搞懂微内核架构
文章目录
- 十分钟搞懂系列
- 什么是微内核架构?
- 如何实现微内核架构?
- 总结
十分钟搞懂系列
序号 | 标题 | 链接 |
---|---|---|
1 | 10分钟带你彻底搞懂企业服务总线 | https://blog.csdn.net/belongtocode/article/details/119487731 |
2 | 10分钟带你彻底搞懂微内核架构 | https://blog.csdn.net/belongtocode/article/details/119107837 |
3 | 10分钟带你彻底搞懂服务限流和服务降级 | https://blog.csdn.net/belongtocode/article/details/119107785 |
4 | 10分钟带你彻底搞懂负载均衡 | https://blog.csdn.net/belongtocode/article/details/118977839 |
5 | 10分钟带你彻底搞懂集群容错和服务隔离 | https://blog.csdn.net/belongtocode/article/details/118968771 |
6 | 10分钟带你彻底搞懂注册中心 | https://blog.csdn.net/belongtocode/article/details/118639474 |
7 | 10分钟带你彻底搞懂RPC架构 | https://blog.csdn.net/belongtocode/article/details/118639448 |
在日常开发过程中,我们经常会遇到这样的需求:针对某个业务场景,我们希望在系统中添加一种新的处理逻辑,但又不想对现有的系统造成太大的影响。从架构设计上讲,这是一种典型的系统扩展性需求。
针对这样的扩展性需求,本质上开发人员想要的是一种类似插件化的架构体系,调用者通过一个插件工厂获取想要的插件,而插件工厂则基于配置动态创建对应的插件,这样整体系统就像搭积木一样可以进行动态的组装。
基于插件化系统,我们往现有系统中添加新的业务逻辑时,就只需要实现一个新的插件并替换老的插件即可,系统的扩展性得到了很好的保证。
那么如何实现这样的插件系统呢?微内核(MicroKernel)架构就是业界主流的实现方案。
什么是微内核架构?
微内核架构包含两部分组件,即内核系统和插件。
这里的内核系统用来定义插件的实现规范,并管理着插件的生命周期。而各个插件是相互独立的组件,各自根据实现规范完成某项业务功能,并嵌入到内核系统中。
显然,基于微内核架构,当面对系统中的某个组件需要进行修改时,我们要做的只是创建一个新的组件并替换旧组件,而不需要改变原有组件的实现方式,更不需要调整整个系统架构。
那么这里的插件具体指的是什么呢?
这就需要我们引入一个概念,即 SPI(Service Provider Interface),也就是服务提供接口。你可以理解为,SPI 就是应对系统扩展性的一个个扩展点,也是我们对系统中所应具备的扩展性的抽象。
插件化实现机制说起来简单,做起来可不容易。我们要考虑两方面内容。
一方面,我们要梳理系统的变化并把它们抽象成 SPI 扩展点。另一方面,当我们实现了这些 SPI 扩展点之后,就需要构建一个能够支持这种可插拔机制的具体实现,从而提供一种 SPI 运行时环境。
那么接下来,我们就来一起讨论微内核架构的具体技术体系怎么搭建,进而实现我们需要的插件系统。
如何实现微内核架构?
微内核架构本质上只是为我们提供了一种架构模式,并没有规定具体的实现方式,所以原则上我们也可以提供一套满足自身要求的实现方案。但是,我们不想重复造轮子。
幸好,JDK 已经为我们提供了微内核架构的一种实现方式,这种实现方式针对如何设计和实现 SPI 提出了一些开发和配置上的规范。
对于 SPI 的实现者而言,具体有三个步骤。
对于 SPI 而言,我们需要设计一个服务接口,然后根据业务场景提供不同的实现类。然后在 Java 代码工程的 META-INF/services 目录中创建一个以服务接口命名的文件,并配置对应的想要使用的实现类。在代码工程中执行这些步骤,最终我们得到了一个包含 SPI 类和配置的 jar 包。
而对于 SPI 的使用者,就可以通过 jar 包中 META-INF/services/ 目录下的配置文件找到具体的实现类名并进行实例化。
上图中的后面两个步骤实际上都是为了遵循 JDK 中 SPI 的实现机制而进行的配置工作。
接下来,我就通过简单的代码示例来给你演示一下这些步骤。
让我们来模拟这样一个应用场景,一般业务系统中都会涉及日志组件,我们希望对业界主流的日志工具做一层包装,以便支持日志组件的灵活应用。
那么,基于 SPI 的约定,我们将创建一个单独的工程 log-spi 来存放服务接口,并给出接口定义,请注意这个服务接口的完整类路径为 com.spi.LogProvider,接口中只包含一个记录 info 日志的简单示例方法。
package com.spi;public interface LogProvider {
// 记录 Info 日志
public void info(String info);
}
假设系统在设计之初使用的是 log4j 日志库。然后我们需要实现这个服务接口,这里创建另一个代码工程 log-log4j 用来提供基于 log4j 日志库的实现,请注意,这个实现类的名称是 Log4jProvider。
public class Log4jProvider implements LogProvider{@Override
public void info(String info){
System.out.println("Log4j:” + info);
}
}
接下来的这个步骤很关键,在这个代码工程的 META-INF/services/ 目录下需要创建一个以服务接口完整类路径命名的文件,文件的内容就是指向该接口所对应的实现类。显然,当前的这个实现类就是前面创建的 Log4jProvider。
最后,我们需要创建一个外部工程 log-consumer 来调用服务接口,首先需要将 log-log4j 所生成的 jar 包添加到这个外部工程中的类路径中。然后,我们使用 JDK 中 ServiceLoader 工具类来完成对 LogProvider 实例的加载。
在这里,我们通过 ServiceLoader.load 方法获取所有的 LogProvider 实例,然后遍历这些实例并调用服务接口方法。
import java.util.ServiceLoader;
import com.spi.LogProvider;public class Main {
public static void main(String[] args) {ServiceLoader<LogProvider> loader = ServiceLoader.load(LogProvider.class);for (LogProvider provider : loader) {
System.out.println(provider.getClass());
provider.info(“testInfo”);
}
}
}
运行这段代码,我们会得到系统的输出。可以看到这里获取的是针对 log4j 的 Log4jProvider 类中的具体方法实现,表示整个 SPI 实例的加载过程是正常的。
class com.spi.Log4jProvider
Log4j:testInfo
请注意,在上面这个 Main 函数中,我们并没有引入任何与 Log4jProvider 相关的包结构,但在运行过程中,却实现了对 Log4jProvider 类的动态调用,这是怎么回事呢?
这就是微内核架构的核心特征,对组件之间的依赖关系进行了解耦,从而确保了系统的扩展性。
现在,我们再来考虑这样一种场景。随着工具的更新或者架构的调整,我们需要提供一套基于 logback 日志库的日志实现来替换现有的基于 log4j 的方案。
当然,我们可以重构原有代码来达成这个目标。但基于扩展性考虑,更好的办法是提供另一个 SPI 实例。这样,我们就可以创建新的代码工程 log-logback,并完成对 LogProvider SPI 接口的实现。请注意,这次的实现类的名称是 LogbackProvider。
public class LogbackProvider implements LogProvider {@Override
public void info(String info){
System.out.println("Logback:” + info);
}
}
同样,我们需要在这个代码工程的 META-INF/services/ 目录下创建一个配置文件,并指向新创建的 LogbackProvider 类。
接下来我们把 log-logback 所生成的 jar 包也添加到外部工程的类路径中,完成这些操作之后,我们再来执行前面的 main 函数,得到的就是来自 Log4jProvider 和 LogbackProvider 类中的输出结果。
class com.spi.Log4jProvider
Log4j:testInfo
class com.spi.LogbackProvider
Logback:testInfo
当然,你可以根据需要提供任何 LogProvider 接口的实现类并动态集成到系统的执行流程中。
不过要注意的是,无论是添加、替换还是移除具体的 SPI 实现,对于原有的 log-consumer 工程而言,我们并没有做任何的代码调整。
这就满足了我们在开篇时提到的扩展性设计理念,就是在现有系统中添加新的组件时,不会对现有系统造成太大的影响。
总结
以上就是这节课的全部内容了。
我们明确了微内核架构模式是实现系统扩展性的有效手段,在 Dubbo、ShardingSphere、Skywalking 等主流的开源框架中都有广泛应用。
而 JDK 提供的 SPI 机制以及 ServiceLoader 工具类为我们实现微内核架构提供了技术方案,帮助我们更好地把这一架构模式应用到了日常开发工作中。
最后,我想给你留一道思考题:想要使用 JDK 中提供的 SPI 机制来实现微内核架构,开发人员需要完成哪些步骤呢?
参考文章:
整理于极客时间每日一课对应文章
10分钟带你彻底搞懂微内核架构相关推荐
- 10分钟带你彻底搞懂服务限流和服务降级
文章目录 十分钟搞懂系列 服务限流 计数器法 滑动窗口法 漏桶算法 令牌桶算法 服务降级 十分钟搞懂系列 序号 标题 链接 1 10分钟带你彻底搞懂企业服务总线 https://blog.csdn.n ...
- 10分钟带你彻底搞懂负载均衡
文章目录 十分钟搞懂系列 负载均衡是如何保证软件系统的生产部署的? 负载均衡分发策略 请求由谁来分发? 服务器端负载均衡器 客户端负载均衡 请求分发到哪去? 静态负载均衡算法 动态负载均衡算法 十分钟 ...
- 8分钟带你深入浅出搞懂Nginx
8分钟带你深入浅出搞懂Nginx Nginx是一款轻量级的Web服务器.反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用. 架构图 上图基本上说明了当下流行的技术架构 ...
- 原码一位乘法器设计_十分钟带你彻底搞懂原码、反码、补码
点击上方"程序员大白",选择"星标"公众号 重磅干货,第一时间送达 编辑 | 程序员大白公众号来源丨https://www.cnblogs.com/zhangz ...
- 泛型类有什么作用_3 分钟带你彻底搞懂 Java 泛型背后的秘密
优质文章,及时送达 作者 | 的一幕 来源 | www.jianshu.com/p/dd34211f2565 这一节主要讲的内容是java中泛型的应用,通过该篇让大家更好地理解泛型,以及面试中经常说的 ...
- 【CSS】5分钟带你彻底搞懂 W3C IE 盒模型
前言 大家好,我是HoMeTown,CSS是作为前端必有技术栈之一,但是有很多同学其实对CSS的盒模型都不是很了解,今天想聊一下Css盒子模型. 盒模型是什么 首先当一个Document对进行布局(l ...
- java编程石头剪刀布图片_石头、剪刀、布!10分钟带你打开深度学习大门,代码已开源...
原标题:石头.剪刀.布!10分钟带你打开深度学习大门,代码已开源 沉沉 发自 宇宙中心 量子位 出品 | 公众号 QbitAI 深度学习技术的不断普及,越来越多的语言可以用来进行深度学习项目的开发,即 ...
- 怎么用Python写出随时间变化的字_面试必备 | 带你彻底搞懂 Python 生成器
文章转载地址:面试必备 | 带你彻底搞懂 Python 生成器. 写在之前 Python 的高级语言特性一直是我们学习 Python 的一个难点,大部分人并没有做到熟练的掌握,甚至去学习它都感觉很困难 ...
- proe常用c语言语句,带你轻松搞懂Proe条件语句
原标题:带你轻松搞懂Proe条件语句 本文通过几个简单的例子介绍Proe中的条件语句,希望对你能有所帮助.Proe中使用的IF条件语句和C语言中的IF语句原理是一样的,其结构稍有差别.首先我们了解一下 ...
最新文章
- 打包、压缩、文件查找、通配符
- nosql和rdnms_用于SaaS和NoSQL的Jdbi
- 谈谈阿里所谓的——要性
- 算法学习之路|最小生成树——prime算法
- 英超必way体育:曼城6-3曼联,帽子戏法太厉害了
- 点聚AIP电子签章在Chrome、Edge新内核、360系列、FireFox、IE、Opera等浏览器中实现网页内嵌效果案例(一)
- css 实现一个尖角_css中尖角的制作实例方法总结
- 安装SQL 2000 企业版
- 数学建模-模糊综合评价分析法原理笔记
- Thrift入门学习
- thingJS模模搭(campusbuilder/momoda)及3dsmax插件遇到的坑
- 手把手教你使用--常用模块--HC05蓝牙模块,无线蓝牙串口透传模块,(实例:手机蓝牙控制STM32单片机点亮LED灯)
- 软件工程面向对象分析
- Android实现朋友圈的评论和回复
- 计算机北大核心期刊不要审稿费,这些核心医学期刊不收取审稿费(建议收藏)...
- 全面解析大数定律:大数定律实现超额增长!
- [已修复] CredSSP 加密 Oracle 修复
- 付子玉:丁香园医疗领域图谱的构建与应用
- redis-setnx-实现原理
- pyspark特征工程常用方法(一)