第四章:微内核架构
微内核架构风格是一种高度灵活且可扩展的架构,允许开发人员或最终用户以插件形式轻松地为现有应用程序添加额外功能和特性,而不会对系统的核心功能产生任何影响。因此,微内核架构常被称为"插件化架构"(这也是其另一个常见名称)。该架构风格非常适合产品型应用程序(即以典型第三方产品版本形式打包并提供下载),同时也广泛应用于定制化企业内部业务应用程序。实际上,许多操作系统都采用了微内核架构风格,并由此得名。
拓扑结构
微内核架构风格由核心系统和插件模块两种类型的架构组件组成。应用逻辑被分为独立的插件模块和基本的核心系统,从而提供了可扩展性、灵活性和隔离性,使得应用功能和自定义处理逻辑更加容易实现。图4-1说明了微内核架构风格的基本拓扑结构。在这种架构风格中,核心系统可以具有不同程度的功能差异。传统上,它只包含最小限度所需的功能(例如旧版IDE如Eclipse),但也可以更加全面(例如像Chrome这样的Web浏览器)。无论哪种情况,在使用单独插件模块来扩展核心系统中功能方面都是非常有效且便捷。
Figure 4-1. Microkernel architecture style
插件模块是独立且独立的组件,包含专门处理、附加功能、适配器逻辑或自定义代码,旨在增强或扩展核心系统以提供额外的业务能力。通常情况下,插件模块应该与其他插件模块相互独立,并且不依赖其他插件来运行。在这种架构风格中,保持最小化的插件间通信非常重要,以避免混乱的依赖问题。
核心系统需要了解可用的插件模块及其访问方式。一种常见实现方式是通过一个插件注册表来实现。注册表包含有关每个插件模块的信息,包括名称、合同细节和远程访问协议细节(取决于将该插件连接到核心系统时使用了哪种协议)。例如,在税务软件中用于标记项目为触发审计高风险项并进行审核检查的插件可能具有一个注册表条目,其中包含服务名称(AuditChecker)、合同细节(输入数据和输出数据)和合同格式(XML)。当合同和访问协议在系统内部标准化时,在注册表中可能只需包含插件模块名称和调用该接口所需接口名称。
插件模块可以通过多种方式与核心系统连接。传统上,插件以独立的库或模块(如JAR和DLL文件)的形式实现,并通过点对点方式进行连接(例如通过接口进行方法调用)。这些独立模块可以通过框架(如OSGi、Java Modularity、Jigsaw、Penrose和Prism或.NET环境)进行管理。当以此方式部署插件时,整体部署模型是单一结构。在使用点对点插件时,微内核架构通常采用将文件放入特定目录并重新启动应用程序等技术。之前提到的某些框架还支持运行时插件功能,允许添加或更改插件而无需重新启动核心系统。
另一种实现插件的方式是将其作为单个集成代码库的一部分,仅通过命名空间或包结构来体现。例如,一个用于电子回收应用程序中对特定电子设备(如iPhone 12)进行评估的插件可能具有命名空间app.plugin.assessment.iphone12。请注意,此命名空间的第二个节点指定了该代码是专门用于评估iPhone 12设备的插件。以这种方式,插件中的代码与核心系统中的代码相互独立。
插件模块也可以作为远程服务实现,并通过REST或消息接口从核心系统访问。在这种情况下,微内核架构将被视为分布式架构。所有请求仍然需要经过核心系统才能到达插件模块,但这种配置允许更容易地运行时部署插件组件,并且如果需要调用多个插件来处理单个业务请求,则可能具有更好的内部可扩展性和响应性能力。
示例
微内核架构的一个典型案例是Eclipse IDE。下载基本的Eclipse产品只会提供一个简单的编辑器。然而,一旦添加插件,它就能变成一个高度可定制和实用的软件开发工具。互联网浏览器是另一个常见使用微内核架构的示例:查看器和其他插件增加了在基本浏览器(核心系统)中无法找到的额外功能。事实上,许多开发者和部署流水线工具以及产品如PMD、Jira、Jenkins等都采用了微内核架构来实现。
产品型软件的例子数不胜数,但是对于小型和大型企业应用程序来说,微内核架构的使用有何优势呢?微内核架构同样适用于这些情况。税务软件、电子回收甚至保险应用都可以从这种架构风格中获益。
以典型保险公司的理赔处理为例(例如事故、火灾、自然灾害等),此类软件功能通常非常复杂。每个司法管辖区(例如美国的一个州)对保险理赔所允许和不允许的规定都有不同。例如,某些司法管辖区允许在挡风玻璃被石头损坏时进行免费更换,而其他司法管辖区则不行。这给标准理赔流程带来了几乎无限多的条件变化。
因此,在大多数保险理赔应用程序中采用庞大而复杂的规则引擎来处理其中很多复杂性是很常见的做法。然而,这些规则引擎可能会演变成一个复杂且难以维护的系统,在更改一个规则时会影响其他规则或需要一支由分析师、开发人员和测试人员组成团队才能进行简单规则修改。使用微内核架构风格可以缓解许多这些问题。
例如,在图4-2中看到的文件夹堆栈代表了理赔处理系统的核心部分,它包含了保险公司处理索赔所需基本业务逻辑(很少变动),但没有包含任何特定司法管辖区相关内容。相反,插件模块包含了每个司法管辖区具体规则信息,并且可以通过自定义源代码或单独运行实例化出来作为规则引擎实现方式;关键点是特定于司法管辖区 的 规 则 和 处 理 是 与 核 心 理 赔 系 统 分 开 的 , 可 以 随 意 增 加 、 删 除 和 更 改。
Figure 4-2. Microkernel architecture example of processing an insurance claim
斟酌与分析
微内核架构风格非常灵活,可以在不同粒度上进行灵活变化。该架构既可用于描述系统的总体结构,也可作为其他架构风格的一部分嵌入和使用。例如,特定的事件处理器、领域服务甚至微服务都可以采用微内核架构风格来实现,即使其他服务以不同方式实现。
这种架构风格对于演进设计和增量开发提供了良好支持。您可以创建一个最小核心系统,提供系统的主要功能,并随着系统逐步演进而添加功能和特性,无需对核心系统进行重大更改。
根据如何实施和使用该架构风格,它既可被视为技术层面上划分的架构,也可被视为领域层面上划分的架构。例如,在技术层面上使用插件提供适配器功能或特定配置将其转化为技术层面上划分的架构;而在领域层面上使用插件提供附加扩展或额外功能将其更像是领域层面上划分的架构。
什么时候考虑这种风格
微内核架构风格是在考虑作为产品型应用程序或定制应用程序起点时一个理想选择。特别适合那些计划逐步增加功能或希望控制用户获取哪些功能的产品。
此外,微内核架构也适用于具有多个配置的应用程序或产品,以满足特定客户环境或部署模型需求。插件模块可以指定不同的配置和针对任何特定环境的功能。例如,在云环境中部署的应用程序可能会包含一组不同的插件,作为适配器来适应该特定云供应商提供的服务,而核心系统则包含主要功能并与实际云环境无关。
与分层架构风格相比,微内核架构风格更简单且经济实惠,在预算和时间限制紧张时是一个优秀选择。
什么时候不要考虑这种风格
无论是远程调用还是点对点调用,所有请求都必须通过核心系统进行。因此,核心系统成为这种架构的主要瓶颈,并不适合高度可扩展和弹性的系统。同样地,由于需要将核心系统作为入口点,整体容错能力也较差。
微内核架构的目标之一是减少对核心系统的更改,并将扩展功能和代码变动推向插件模块中,这些模块更加自包含且易于测试和修改。因此,如果你发现大部分变化都在核心系统中,并且没有充分利用插件来包含额外功能,则很可能这种架构并不适合解决你所面临的问题。
架构特征
图4-3中的图表综合评估了微内核架构在体系结构特征方面的整体能力(架构特性)。星级评定表示一颗星代表该架构特性支持较差,而五颗星则表示它非常适用于该特定的架构特性。
Figure 4-3. Architecture characteristics star ratings for the microkernel architecture