0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

从分层架构到微服务架构介绍(四)

jf_78858299 来源:元闰子的邀请 作者:元闰子 2023-05-10 17:00 次阅读

前言

微内核架构 (Microkernel Architecture),也被称为 插件式架构 (plug-in architecture),作为一个在几十年前就被创建出来的架构模式,它如今仍然被广泛应用在各个领域中。比如在Web浏览器领域,谷歌的Chrome浏览器之所以被认为功能强大,一个很重要的原因是它有着丰富的插件类型;在开发工具领域,微软的VS Code初始安装后还只是个简单的文本编辑器,但用户可以安装各种插件,从而让它摇身一变成为功能强大的IDE。

Chrome和VS Code都是微内核架构的典型应用例子,它们提供一个具备最基础能力的核心系统,并定义好插件的开发接口。至于需要开发或安装哪种类型的插件,则完全由普通开发者和用户决定,这样的设计让系统 具备了极强的可定制化和可扩展能力

架构视图

微内核架构由以下两部分组成: 核心系统 (core system)和 插件 (plug-in component), 将应用系统的业务逻辑拆分成核心系统和插件,能够提供很好的可扩展性和灵活性,极大地方便了后续需求的新增和修改

图片

微内核架构架构视图

核心系统

核心系统通常只需提供能够支撑整个系统正常运行的基本功能 ,比如前文所举的VS Code例子,用户初始安装的是VS Code的核心系统,它只是一个提供了打开文件、编辑文件内容和保存文件等基本功能的文本编辑器,其他的扩展功能(如语法检查)都是通过安装插件集成的。 将复杂的业务逻辑从核心系统中剥离出来,并通过插件实现,能够提升系统的可扩展性和可维护性 。同时,因为复杂的功能都成了互不干扰的插件,系统的可测性也得到了提高。

考虑现在需要实现一个电子设备回收系统,在回收之前,每种型号的手机设备的回收流程都不一样,那么我们可以这样去实现:

public void assessDevice(String deviceID) {
   if (deviceID.equals("iPhone6s")) {
      assessiPhone6s();
   } else if (deviceID.equals("iPad1"))
      assessiPad1();
   } else if (deviceID.equals("Galaxy5"))
      assessGalaxy5();
   } else ...
      ...
   }
}

如果我们把assessDevice看成是核心系统,那么后面每次新增一个型号的手机,都需要新增一个if分支,也即对核心系统进行了改动。这样的设计会导致核心系统非常地脆弱,正所谓 改的越多,出问题的概率也越大

比起这种将所有的可定制业务逻辑放在核心系统上的设计,更好的应该是将它们实现为插件的形式,这样不仅每个设备回收逻辑都解耦了,还提供了强大的可扩展性:添加一个新的回收设备类型,只需新增一种插件即可,核心系统无需变动。

public void assessDevice(String deviceID) {
  String plugin = pluginRegistry.get(deviceID);
 DevicePlugin devicePlugin =
  (DevicePlugin)constructor.newInstance();
 DevicePlugin.assess();
}

微内核架构在实现时通常都结合了其他架构模式 ,这主要体现在核心系统的设计上,比如根据具体的业务特点,我们可以将核心系统设计成technically partitioned的分层架构,或者是domain partitioned的模块化架构。

图片

核心系统的架构设计

插件

插件就是一些包含了定制化业务逻辑、扩展功能、附加功能的独立组件,用于扩充核心系统的功能 。插件之间是独立的,插件与核心系统之间则一般是“点对点”通信:核心系统通过调用插件提供的接口(比如插件类的方法)使用扩展功能。

插件可以划分为编译时插件和运行时插件两种类型,前者每次变更都需要重新构建和部署整个系统,但实现较为简单;后者则可以在系统运行时进行插件的新增和删除操作,相对地,实现也较为复杂。

编译时插件

在编译时插件中,插件通常以package或namespace实现,比如在package中可以以这样的命名规则来区分插件:app.plug-in..

图片

编译时插件实现

运行时插件

运行时插件中插件的实现通常是动态库的形式,比如.jar.so.dll文件。在上述的设备回收系统的例子中,每种型号的手机设备回收逻辑包含在一个独立的.jar文件中:

图片

运行时插件实现

远端插件

当然,插件和核心系统并非只能通过本地接口调用进行通信,还可以采用REST/消息队列/RPC等方式,这种场景下,插件就变成了一个独立部署的服务。远程插件具备运行时插件的特点,而且能够提供更好的scalability: 插件和核心系统甚至都不必使用相同的技术栈实现,只需遵守既定的REST接口即可

图片

远端插件

为了提升系统处理请求的responsiveness,我们还可以将核心系统调用插件的过程实现为异步通信 。以前文的电子设备回收系统为例,在异步通信的架构下,系统通过一个线程触发插件启动对某个设备的回收流程。之后,该线程无需一直等待回收结束,它可以去继续回收别的设备。当设备回收结束后,插件会通过异步队列告知核心系统。这样的异步设计可以减少无谓的等待流程,明显改善系统的responsiveness。

如果涉及到读写数据库,为了能够维持插件的独立性,每个插件最好能够拥有独立的数据库 。如果插件间有着无可避免的数据交互,则可以为核心系统配置一个中心数据库,并通过它来进行数据中转。

图片

插件的的独立数据库

插件中心

核心系统在加载插件前,必须得知道 当前有哪些可用的插件 ,以及 这些插件在哪里可以获取 。这要求系统有一个地方去管理插件,这就是 插件中心 (plug-in registry)的功能。插件中心类似于服务化架构中服务注册中心的作用,它保存了所有插件的基本信息,包括名称、数据契约、通信协议、加载地址等。

我们可以简单地将插件中心实现为一个本地的map表,其中key可以是插件名称,value为获取插件的地址:

Map<String, String> registry = new HashMap<String, String>();
static {
  //point-to-point access example
  registry.put("iPhone6s", "Iphone6sPlugin");

  //messaging example
  registry.put("iPhone6s", "iphone6s.queue");

  //restful example
  registry.put("iPhone6s", "https://atlas:443/assess/iphone6s");
}

为了实现一些较为复杂的功能,如插件上下线通知等,我们还可以借助Apache ZooKeeper、ETCD这类的分布式协同系统实现 远程插件中心

通信契约

通信契约定义了插件与核心系统之间的通信方式、交互行为和数据格式。通信方式可以是本地接口调用、REST、RPC、消息队列等;交互行为则可以理解为插件对核心系统提供的接口,比如本地的函数/方法、REST的URI等;对本地插件而言,数据格式通常是一个类/结构体,对远程插件而言,常用的数据格式有JSON、XML、ProtoBuf等。

考虑电子设备回收系统的例子,系统有着如下定义的通信契约:

public interface AssessmentPlugin {
  // 回收设备流程
 public AssessmentOutput assess();
  // 将该插件注册到插件中心
 public String register();
  // 从插件中心去注册
 public String deregister();
}

public class AssessmentOutput {
  // 回收报告,仅仅用于展示结构给用户看,核心系统无需了解该格式
 public String assessmentReport;
  // 用于标识该设备是否可以在二手市场上重新售卖
 public Boolean resell;
  // 表示该设备的价值
 public Double value;
  // 表示推荐的售卖价格
 public Double resellPrice;
}

从该契约定义中可以看出,通信方式为本地接口调用(AssessmentPlugin接口);它有着3个交互行为,assess()为回收设备流程、register()表示将该插件注册到插件中心、deregister表示去注册;数据格式则是AssessmentOutput类,它定义了回收流程的结果。

架构评分

图片

微内核架构的架构评分

和之前介绍的分层架构、管道架构一样,微内核架构同样属于单体架构,因此Simplicity和Overall cost是该架构模式主要优势;而Elasticity、Fault tolerance和Scalability是主要劣势。

另外,微内核架构的Testability、Deployability、Reliability、Modularity之所以能够取得3颗星,得益于不同的功能能够被拆分至独立的插件上,特别地,运行时插件的增删无需重新部署系统。 这使得系统能够快速响应需求变更,具备很高的扩展性 。比如对于前面的电子设备回收系统,如果需要新增一种新的电子设备回收流程,只需新增一个插件即可;如果某种设备不再需要回收,则去除对应插件即可。

微内核架构比较特别的一点是,它既可以是technically partitioned,也可以是domain partitioned,这取决于核心系统的实现方式,前文也有介绍。

总结

Robert C.Martin曾经说过, 软件开发技术发展的历史就是一个如何想方设法方便地增加插件,从而构建一个可扩展、可维护的系统架构的故事 。在敏捷开发的潮流之下,需求的变更如同家常便饭,系统不应该因为某一部分发生变更从而导致其他不相关的部分出现问题。将系统设计为微内核架构,就等于构建起了一面变更无法逾越的防火墙,插件发生的变更就不会影响系统的核心业务逻辑。

微内核架构的设计思想,能够极大提升系统的可扩展性和健壮性 ,在其他的一些软件方法论里,我们也隐约能看到它的影子。比如在领域驱动设计中,领域层就相当于核心系统,它定义了系统的核心业务逻辑;基础设施层则相当于插件,切换不同的基础设施并不会影响系统的业务逻辑,这得益于基础设施层依赖倒置的设计原则。

当然,作为微内核架构也有着一些缺点,它天然具备了单体架构的一些劣势,比如核心系统作为架构的中心节点并不具备Fault tolerance能力。因此,该架构模式往往被广泛应用于一些着重提供很强的用户定制化功能的小型产品,如VS Code等,它们对系统的Elasticity、Fault tolerance和Scalability并没有很高的要求。

每种架构模式都有其合适的应用场景,只有熟悉常用的几种架构模式,才能设计出更好的软件系统。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Web
    Web
    +关注

    关注

    2

    文章

    1255

    浏览量

    69333
  • IDE
    IDE
    +关注

    关注

    0

    文章

    335

    浏览量

    46677
  • 微内核架构
    +关注

    关注

    0

    文章

    5

    浏览量

    6531
  • 浏览器
    +关注

    关注

    1

    文章

    1016

    浏览量

    35274
收藏 人收藏

    评论

    相关推荐

    k8s微服务架构就是云原生吗?两者是什么关系

    k8s微服务架构就是云原生吗?K8s微服务架构并不等同于云原生,但两者之间存在密切的联系。Kubernetes在云原生架构中扮演着核心组件的
    的头像 发表于 11-25 09:39 38次阅读

    SSR与微服务架构的结合应用

    随着互联网技术的快速发展,前端技术栈不断更新迭代,后端架构也经历了单体应用到微服务的变革。在这个过程中,服务端渲染(SSR)作为一种提升页面加载速度和SEO性能的技术,与
    的头像 发表于 11-18 11:34 231次阅读

    GPU服务器AI网络架构设计

    众所周知,在大型模型训练中,通常采用每台服务器配备多个GPU的集群架构。在上一篇文章《高性能GPU服务器AI网络架构(上篇)》中,我们对GPU网络中的核心术语与概念进行了详尽
    的头像 发表于 11-05 16:20 191次阅读
    GPU<b class='flag-5'>服务</b>器AI网络<b class='flag-5'>架构</b>设计

    架构与设计 常见微服务分层架构的区别和落地实践

    架构风格越倾向于清晰的职责定位,且让领域模型成为架构的核心。 基于这些架构风格,在软件架构设计过程中又有非常多的架构
    的头像 发表于 10-22 15:34 149次阅读
    <b class='flag-5'>架构</b>与设计 常见<b class='flag-5'>微服务</b><b class='flag-5'>分层</b><b class='flag-5'>架构</b>的区别和落地实践

    微服务架构与容器云的关系与区别

    微服务架构与容器云密切相关又有所区别。微服务将大型应用拆分为小型、独立的服务,而容器云基于容器技术,为微服务提供构建、发布和运行的平台。区别
    的头像 发表于 10-21 17:28 172次阅读

    入门级攻略:如何容器化部署微服务

    第一步理解容器化基础,第二步创建Dockerfile,第三步构建推送镜像,第步部署微服务,第五步管理微服务、第六步优化更新。容器化部署微服务是现代软件开发中的一种高效方法,可提供良好
    的头像 发表于 10-09 10:08 118次阅读

    服务器而言,ARM架构与X86架构有什么区别?各自的优势在哪里?

    ,x86 架构服务器在市场占主导,有强大处理能力和广泛软件兼容性,广泛用于企业数据中心。ARM 架构服务器近年崛起,凭借低功耗、高效能优势在云计算和
    的头像 发表于 09-09 14:05 1443次阅读

    Proxyless的多活流量和微服务治理

    1. 引言 1.1 项目的背景及意义 在当今的微服务架构中,应用程序通常被拆分成多个独立的服务,这些服务通过网络进行通信。这种架构的优势在于
    的头像 发表于 08-28 16:54 1538次阅读
    Proxyless的多活流量和<b class='flag-5'>微服务</b>治理

    ai服务器是什么架构类型

    AI服务器,即人工智能服务器,是专门为人工智能应用设计的高性能计算服务器。AI服务器的架构类型有很多种,以下是一些常见的
    的头像 发表于 07-02 09:51 934次阅读

    不能独立开发,是因为你不懂软件架构

    不想错过,记得右上角-查看公众号-设为星标,摘下星星送给我嵌入式软件架构设计一般采用分层思想,称为“分层架构”。part1一、什么是分层
    的头像 发表于 03-15 08:09 1114次阅读
    不能独立开发,是因为你不懂软件<b class='flag-5'>架构</b>

    新思科技携手台积公司推出“架构探索签核” 统一设计平台

    新思科技3DIC Compiler集成了3Dblox 2.0标准,可用于异构集成和“架构探索签核”的完整解决方案。
    的头像 发表于 01-12 13:40 492次阅读
    新思科技携手台积公司推出“<b class='flag-5'>从</b><b class='flag-5'>架构</b>探索<b class='flag-5'>到</b>签核” 统一设计平台

    游戏公司不使用微服务架构的原因

    微服务基本只有 request/response 的模式。做不了 streaming?微服务通常要求应用是无状态的才能做到水平扩展。streaming 本身就是加入了状态
    的头像 发表于 12-29 11:18 411次阅读

    如何搭建微服务架构的全局图景

    如果一直保持共用数据库的模式,则整个架构会越来越僵化,失去了微服务架构的意义。因此小明和小红一鼓作气,把数据库也拆分了。所有持久化层相互隔离,由各个服务自己负责。另外,为了提高系统的实
    的头像 发表于 12-27 15:16 472次阅读
    如何搭建<b class='flag-5'>微服务</b><b class='flag-5'>架构</b>的全局图景

    如何构建弹性、高可用的微服务

    基于微服务的应用程序可实现战略性数字转型和云迁移计划,对于开发团队来说,这种架构十分重要。那么,如何来构建弹性、高可用的微服务呢?RedisEnterprise给出了一个完美的方案。文况速览
    的头像 发表于 11-26 08:06 454次阅读
    如何构建弹性、高可用的<b class='flag-5'>微服务</b>?

    设计微服务架构的原则

    微服务是一种软件架构策略,有利于改善整体性能和可扩展性。你可能会想,我的团队需不需要采用微服务,设计微服务架构有哪些原则?本文会给你一些灵感
    的头像 发表于 11-26 08:05 561次阅读
    设计<b class='flag-5'>微服务</b><b class='flag-5'>架构</b>的原则