Skip to content

微内核架构

About 1746 wordsAbout 6 min

架构新书

2026-05-4

定义

微内核架构的系统包含了 系统核心插件。核心提供系统基本功能,以及插件生命周期管理,以及插件与核心,插件与插件通信的功能。 插件则提供了系统的扩展功能。

常见实例

技术案例: 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则采用了混合内核方式。具备微内核和宏内核的优点。

知行合一