微内核架构
定义
微内核架构的系统包含了 系统核心和插件。核心提供系统基本功能,以及插件生命周期管理,以及插件与核心,插件与插件通信的功能。 插件则提供了系统的扩展功能。
常见实例
技术案例: Idea/Eclipse/VS 编辑器、Maven/Vite构建工具、浏览器、网关或者代理服务器、低代码开发平台,多租户系统(注:为每个客户提供特定功能) ,鸿蒙操作系统,物联网操作系统等
描述:
微内核又称为插件系统,通常有如下架构

- 核心:提供了系统的基础功能,以Maven为例子,提供了项目生命周期管理和依赖管理等基本功能;以Idea为例子,提供了编辑器功能,以及按照语法树(PsiTree)语法着色,变量引用,重构等功能
- 插件:提供了系统的扩展功能,以Maven为例子,提供了默认的compile,package,deploy等插件,用户也可以扩展自己的插件完成Maven项目的管理;以Idea为例子,提供了Java语言的语法树解析,Java文件的色方案等功能。用户也可以提供自己语言的语法树解析,文件着色方案,变量引用实现
以Maven构建为例子,它是个典型的,易于理解的插件架构。 Maven核心将软件构建总结为clearn,compile,test,package,install 等阶段,每个阶段内置了插件完成任务,比如Compile插件阶在compile阶段执行,程序员可以配置插件特性,也可以开发自定义插件。下图上展示了Maven的默认生命周期的各个阶段(实际上包含更多的阶段),每个阶段有默认插件实现,因此,使用Maven 构建工程,几乎不需要做任何额外事情。

你可以自定义一个Maven插件,比如定义一个插件,在compile阶段,检测依赖软件,禁止项目出现scope为system的依赖
编写插件,首先通过pom引入编写插件需要的的依赖
<groupId>org.example</groupId>
<artifactId>compile-check-plugin</artifactId>
<version>1.0</version>
<packaging>maven-plugin</packaging>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>编写如下CompileCheck 代码,CompileCheck 类通过注解@Mojo申明了这个插件的阶段是LifecyclePhase.COMPILE,goal的名称是“dependency-check”
@Mojo(name = "dependency-check", defaultPhase = LifecyclePhase.COMPILE)
public class CompileCheck extends AbstractMojo {
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
//调用核心提供的功能,获取所有依赖
List<Dependency> dependencies = project.getDependencies();
//核心的日志系统
getLog().info("check dependency scope " + dependencies.size());
for(Dependency dependency:dependencies){
if(dependency.getScope().equals("system")){
throw new MojoFailureException("不允许 system scope "+dependency.getGroupId()+":"+dependency.getArtifactId());
}
}
}
}代码第三行注解@Parameter 可以从maven插件框架注入一个所需要的变量,这里是MavenProject ,指当前工程project。
代码第8行调用Maven核心提供的API方法getDependencies获取Project中获取所有的依赖
代码10行 调用 getLog() 提供的打印日志的服务,这里向控制台输出检查的依赖总数
代码11行-15行,CompileCheck 类通过循环,以此检测依赖是否存在Scop为system,如果有,则抛出MojoFailureException,中断整个打包过程。
安装如上工程后,进入任何Maven工程,可以运行dependency-check
> mvn clean install
> mvn org.example:compile-check-plugin:1.0:dependency-check最典型的插件架构的实现IDE编辑器,以Idea为例子,其核心提供了IDE编辑器的基本文本编辑,文本着色。其他功能,如语法着色,语法提示,折叠,格式化,重构,括号匹配等,需要通过插件实现。这些插件无需了解编辑器如何实现着色,语法提示,折叠等。 如下是一个某脚本语言的实现的插件配置:
<extensions defaultExtensionNs="com.intellij">
<!-- 定义一种叫Beetl的脚本语言 -->
<fileType name="Beetl" implementationClass="com.intellij.ibeetl.lang.BeetlFileType"
fieldName="INSTANCE" language="Beetl" extensions="btl"/>
<!-- 解析文本为语法树的插件-->
<lang.parserDefinition language="Beetl"
implementationClass="com.intellij.ibeetl.lang.BeetlParserDefinition"/>
<!-- 语法提示插件 -->
<completion.contributor language="Beetl"
implementationClass="com.intellij.ibeetl.contributor.BeetlContributor"/>
<!-- 语法着色插件 -->
<lang.syntaxHighlighterFactory language="Beetl"
implementationClass="com.intellij.ibeetl.lang.highlight.BeetlSyntaxHighlighterFactory"/>
<!-- 支持此脚本能嵌入到其他语言中,类似Java中的注释语法,HTML中的script脚本 -->
<multiHostInjector implementation="com.intellij.ibeetl.inject.BeetlMultiHostInjector"/>
<!-- 折叠功能插件 -->
<lang.foldingBuilder language="Beetl" implementationClass="com.intellij.ibeetl.fold.BeetlFolding"/>
<!-- 括号匹配插件 -->
<lang.braceMatcher language="Beetl" implementationClass="com.intellij.ibeetl.match.BeetlMatch"/>
<!-- 格式化功能插件 -->
<lang.formatter language="Beetl"
implementationClass="com.intellij.ibeetl.formatter.BeetlFormattingModelBuilder"/>
</extensions>当我们想为Beetl脚本实现着色的时候,插件只需要告诉IDE, Beetl的语法树的节点类型应该用什么颜色即可。实现getTokenHighlights方法
@Override
public TextAttributesKey[] getTokenHighlights(IElementType tokenType ) {
//判断语法节点的类型
if(tokenType instanceof TokenIElementType ){
TokenIElementType antlrTokenType = (TokenIElementType)tokenType;
//当节点是数字类型
if(antlrTokenType.getANTLRTokenType()== BeetlLexer.DecimalLiteral){
//BTL_NUMBER是一个跟颜色定义相的类,
return new TextAttributesKey[]{BTL_NUMBER};
}
//当节点是ID时候
else if(antlrTokenType.getANTLRTokenType()==BeetlLexer.Identifier){
return new TextAttributesKey[]{BTL_IDENT};
}
..... //省略其他代码
}当实现括号匹配功能时候(即鼠标指左做括号,其左括号对应的右括号自动),需要告诉IDEA 其匹配规则即可
//定义一对‘{’ 和 ‘}’
static TokenIElementType[] brace = find(BeetlLexer.LEFT_BRACE,BeetlLexer.RIGHT_BRACE);
//定义一对‘(’和‘)’
static TokenIElementType[] par = find(BeetlLexer.LEFT_PAR,BeetlLexer.RIGHT_PAR);
private final BracePair[] pairs = new BracePair[]{
new BracePair(brace[0], brace[1], true),
new BracePair(par[0], par[1], true),
};
@Override
public BracePair @NotNull [] getPairs() {
return pairs;
}
/* 还需要实现其他辅助方法,这里省略了*/关于Beetl语法树,可以参考分层架构的语言编译例子
需要注意的是,微内核架构早期概念是相对于宏内核架构,用于操作系统架构。 在分层架构中,我们知道系统内核是应用的基础,在Linux系统上,采用的是宏内核架构,内核包含了进程管理,进程通信,内存管理,文件服务,驱动服务等,这些服务作为一个整体是一个大进程,服务之间调用是函数调用,效率很高。宏内核的缺点是内核太大,不容易维护,而且,如果某个服务出现崩溃,整个进程都会崩溃,则系统崩溃。
而微内核的会只保留核心的功能,如进程管理,内存管理,进程通信,内核较小,其他服务可以插拔。可以引用于除了PC机外,还能应用在手机,物联网,车联网的操作系统上进程之间通过 IPC 进行通信,高度模块化,一个服务的故障不会影响另一个服务。不过由于模块化的影响,宏内核那种进程内通信完成服务被进程间通信代替,效率较低。
Window和Mac OS则采用了混合内核方式。具备微内核和宏内核的优点。
