什么是微内核架构设计?

简介: 作为一名Java程序员,相信同学们都听说过微内核架构设计,也有自己的理解。那么微内核是如何被提出来的?微内核在操作系统内核的设计中又有什么作用?本文从插件化(Plug-in)架构的角度来诠释微内核架构设计,通过微内核架构和微服务架构的对比,分享其对微服务设计的参考意义。

image.png

关于微内核架构设计现在比较热,听起来好像是操作系统内核相关的,作为Java程序员,操作系统内核那么遥远的事情,好像和我们没有什么关系。但是如果我说微内核其实就是插件化(Plug-in)架构,你一定会一脸疑惑,“你居然向Java程序员解释什么是插件化架构?我每天都在用啊,Eclipse、IntelliJ IDEA、OSGi、Spring Plugin、SPI等,哪个不是插件化架构。我的一些项目也是采用插件化设计的,如使用插件实现流程控制定制等等”。但是别着急,即便是我们每天都在使用的技术,而且大多数人也都知道,如果我们能将其阐述得更清楚,并且能从中发现一些问题,做出一些优化有助于以后的架构设计,那么大多数人在日常的设计和开发中都能受益,岂不是更好。现在我们就来聊一聊微内核架构设计。

一 微内核设计之操作系统内核

微内核设计其实就是插件体系。我们都知道,操作系统内核诞生得比较早,所以插件化最早被用在内核设计上,于是就有了微内核设计这一称呼。

微内核是这样一种内核:它只完成内核不得不完成的功能,包括时钟中断、进程创建与销毁、进程调度、进程间通信,而其他的诸如文件系统、内存管理、设备驱动等都被作为系统进程放到了用户态空间。说白了,微内核是相对于宏内核而言的,像Linux就是典型的宏内核,它除了时钟中断、进程创建与销毁、进程调度、进程间通信外,其他的文件系统、内存管理、输入输出、设备驱动管理都需要内核完成。

也就是说,微内核是相对宏内核而言的,宏内核是一个包含非常多功能的底层程序,也就是我们现在讲的Monolith。它干的事情非常多,而且不是可插拔的,修改一些小的功能,都会涉及到整个程序的重新编译等,比如一个功能出现了一个小bug,可能导致整个内核都出问题。这也是很多人将Linux称为monolithic OS的原因。而微内核只负责最核心的功能,其他功能都是通过用户态独立进程以插件方式加入进来,然后微内核负责进程的管理、调度和进程之间通讯,从而完成整个内核需要的功能。基本一个功能出现问题,但是该功能是以独立进程方式存在的,不会对其他进程有什么影响从而导致内核不可用,最多就是内核某一功能现在不可用而已。

微内核就是一个运行在最高级别的程序片段,它能完成用户态程序不能完成的一些功能。微内核通过进程间通信来协调各个系统进程间的合作,这就需要系统调用,而系统调用需要切换堆栈以及保护进程现场,比较耗费时间;而宏内核则是通过简单的函数调用来完成各个模块之间的合作,所以理论上宏内核效率要比微内核高。这个和微服务的架构设计一样,我们将Monolith应用划分为多个小应用后,系统的设计就变得比较复杂了,之前都是应用内部函数调用,现在要涉及网络通讯、超时等问题,同时响应时间会被拉长。

聊到这里,相信大家对微内核和宏内核已经有了一个大致的了解,看起来各有千秋。但是宏内核有一个最大的问题就是定制和维护陈本。现在的移动设备和IoT设备越来越多,如果要把一个庞大复杂的内核适配到某一设备上,是一件非常复杂的事情,如果很简单的话,那么把Linux内核适配到Android内核,甚至到Tesla等车载系统,基本上人人都可以做了。

因此我们更需要一个微内核的架构设计,方便定制,而且非常小,可以实现功能的热替换或者在线更新等,这就是微内核被提出来的核心需求。但是微内核有一个运行的效率问题,所以在微内核和宏内核之间,又有了Hybrid内核,主要是想拥有微内核的灵活性,同时在关键点上有宏内核的性能。微内核设计在理论上确实有效率问题,但是随着芯片设计、硬件性能提升等,这方面或许已经有了非常大的提升,已经不再是最关键的问题。

总体下来,内核设计有三个形式,如下:

image.png

二 插件化(Plug-in)架构设计

上面聊了微内核在操作系统内核设计中的作用,接下来我们就开始讨论更通用的插件化架构设计,毕竟这个词大家都明白。

插件化架构非常简单,就两个核心组件:系统核心(Core System)和插件化组件(Plug-in component)。Core System负责管理各种插件,当然Core System也会包含一些重要功能,如插件注册管理、插件生命周期管理、插件之间的通讯、插件动态替换等。整体结构如下:

image.png
插件化架构对微服务架构设计帮助非常大,考虑到隔离性,插件可能是以独立进程方式运行的,那么这些进程如果扩展到网络上,分布在众多的服务器上,这个就是微服务架构的原型,所以了解微内核的同学都不屑于和你讨论微服务架构,相信你也明白了,除了IT传统的鄙视链因素,原理上确实就是这么回事。

回到微服务架构设计场景,我们将Plug-in component重新命名为服务(Service),这个和微内核设计中的服务也差不多,这个时候微服务和微内核就差不多了,都涉及到服务注册、管理和服务之间的通讯等。那我们看一下微内核是如何解决服务之间的通讯问题的?以下摘自维基百科:

因为所有服务行程都各自在不同地址空间运行,因此在微核心架构下,不能像宏内核一样直接进行函数调用。在微核心架构下,要创建一个进程间通信机制,通过消息传递的机制来让服务进程间相互交换消息,调用彼此的服务,以及完成同步。采用主从式架构,使得它在分布式系统中有特别的优势,因为远程系统与本地进程间,可以采用同一套进程间通信机制。

也就是说,采取的是基于消息的进程间通讯机制。消息最简单,就两个接口:send和receive,消息发送出去,然后等着收消息,处理后再发消息就可以了,这里大家应该也知道了,这个是异步的。回到插件化架构设计中,Plug-in组件设计包含交互规范,也就是和外界相互通讯的接口,如果是基于消息通讯的话,就是send和receive接口,可以说是非常简单的。

但是这里还有一个问题,那就是进程间通讯。你可能会问,这个有什么好疑问的,就是两个进程之间相互发消息呗。但是这里有一个最大的疑问,那就是进程间通讯是否有第三者介入?如下图:

 

image.png

当然在操作系统的内核设计中,一定是通过内核进行转发的,就是我们理解的总线架构,内核负责协调各个进程间的通讯。这个大家也能理解,如果进程A直接发给另外一个进程B,必然要了解对应的内存地址,微内核中的服务是可以被随时替换的,如果服务不可用或者被替换,这个时候要通知和其通讯的其他进程,是不是太复杂?刚才已经提到,只有send和receive接口,没有其他通知下线、服务不可用的接口。在微内核的设计中,一定是通过总线结构,进程向Kernel发送消息,然后kernel再发送给对应的进程,这样的一个总线设计。实际上很多应用内部在做Plug-in组件解耦时,都会使用EventBus的结构,其实就是总线的设计机制。

为何婆婆妈妈说这些?因为非常关键。分布式的进程通讯是微服务的核心,我们理解的服务到服务的通讯,就是服务A启动监听端口,服务B会和服务A建立连接,然后两者通讯即可。这个方式和微内核设计中内核负责消息接收和转发的总线架构设计是不一样的。如采用HTTP,HSF等通讯协议时,相当于kernel告知通讯的双方各自的地址,然后它们之间就可以通讯了。然后就没有Kernel什么事情了,也不会用到什么总线的结构设计,这个就是传统的服务发现机制。

但是还有一种模式,就是完全透明的插件化通讯机制,如下图:

 

image.png

Plug-in组件,也就是微服务架构中的服务,是不能直接通讯的,而是需要Core System进行转发。这样做的好处和微内核架构一样,插件相互之间无直接联系,彼此之间非常透明,例如服务A下线后,完全不需要通知其他服务;服务A被替换,也不需要通知其他服务;服务A从数据中心1到数据中心2,也不用通知其他服务;即便服务N和服务A之间网络不互通,两者之间也能通讯。

这里有个问题:性能问题。我们都知道,两点之间,直线段最短。为何要多绕一下到Core System呢?这就是微内核和宏内核之间的争论之处,使用函数调用非常快,而进程间的消息通讯则是非常慢的,但是这种通过中介进行通讯机制的好处也是非常明显的。那么如何提升这种基于总线的通讯性能呢?当然有,比如选择高性能的二进制协议,HTTP 1.1这种文本协议就不需要了;采用Zero Copy机制,可以快速进行网络包转发;好的网络硬件,如RDMA;好的协议,如基于UDP的QUIC等。总结下来,和微内核一样,这种微服务通讯的性能是可以提升的。当然如果实在受不了这种性能,在关键场景,你可以采用Hybrid模式,混入一些服务之间直接通讯的设计,但只能在性能极致的场景中使用。

此外,插件化架构中的插件组件是各种各样的,通讯的机制也各不一样,一些是RPC的,一些是Pub/Sub的,一些是无需ACK的(如Beacon接口),还有一些是双向通讯的等等。当然你可以选择不同的通讯协议,但是这里有一个问题,就是Core System需要理解这个协议,然后才能进行消息路由。这个时候Core System需要编写大量的Adapter来解析这些协议,例如Envoy包含各种filter来支持不同的协议,如HTTP、MySQL、ZooKeeper等,但是因此Core System就会变得非常复杂且不稳定。

另外可以选一种通用的协议,Core System只支持这一种协议,各个插件之间都基于该协议通讯,至于服务和其他外部系统如何通讯,如数据库、github集成等,这些Core System并不关心,那只是Service内部的事情。目前比较通用的协议是gRPC,如K8s内部都会采用该协议,另外Dapr也采用gRPC协议做服务集成,因为gRPC提供的通讯模型基本可以满足大多数的通讯场景。当然另外一个就是RSocket,提供更丰富的通讯模型,也适用于Core System这种服务间通讯场景。对比gRPC,RSocket可以运行在各种传输层上,如TCP、UDP、WebSocket、RDMA等,相反的,gRPC目前只能运行在HTTP 2之上。

三 服务通讯的延伸

前面说到,最好由插件化架构设计的Core System作为服务之间消息通讯的路由,如果是这样的话,就会产生一种Broker模式,当然也有可能是Agent。这里大家一定会想到Service Mesh,没错。当然你可以选择Agent Sidecar模式,也可以选择中心化的Broker模式,这两者的功能都是一样的,只是处理的方式不一样而已。Agent基于服务注册和发现机制,然后找到对方服务的Agent,再进行两个Agent之间的通讯,只是省掉服务之间的调用的开销。但是Broker是集中式的,大家都向Broker发送和接收消息,不涉及服务注册发现机制,不涉及服务元信息推送,就是总线结构。

我现在做的就是基于这种Broker的总线的架构设计,在RSocket Broker中,也是采用微内核架构设计,当然未必做得最好 。RSocket Broker核心就是管理注册的服务、路由管理、数据采集等,而不会添加过多的功能,和Core System的设计理念一样,只添加必须的功能。如果你要扩展整个系统更多的功能,如发短信、发邮件、对接云存储服务等,需要编写一个Service ,然后和Broker对接一下,再从broker那里收消息(receive),处理完毕后再发送(send)给Broker就可以了。总体结构如下:

image.png

有不少同学会问,当服务实例的负载太高的时候,Broker如何实现动态扩容呢?Broker会给你提供数据,如一个服务实例QPS,至于是否扩展,你只需要写一个服务,从Broker上采集数据,分析后,调用K8s API进行扩容即可,Broker并不负载这些业务功能,它只会添加非常必要的功能,这个和Core System设计是一样的。

回到插件化架构的灵活性上,如果系统中有一个KV存储的插件,你只要遵循消息格式或者通讯接口,就可以保存KV数据。但是你并不太关心是Redis存储的,还是Tair存储的,或者是云端的KV服务,这就为服务标准化和可替换性提供了很好的基础,这对应用上云或云原生化帮助非常大,整个系统有非常大的灵活性。

四 总结

其实有非常多的书有关于微内核的介绍,操作系统的图书就不用说了,另外两本书也非常不错,对通用架构设计帮助也非常大,尤其是微服务的场景,我也是参考这两本书写这篇文章的。

 

image.png

微内核架构设计对微服务设计有非常好的参考意义,但是微服务有一个非常大的问题就是服务边界的划分,对比操作系统,已经发展几十年,而且非常稳定,功能划分非常容易。而微服务架构是为业务服务的,虽然面对的业务可能已经存在上百年,但是软件化、数字化和流程化并没有多少年,加上现实业务的复杂性,还有各种妥协,个人认为微服务架构会更复杂一些。

作者:开发者小助手_LS

原文链接

本文为阿里云原创内容,未经允许不得转载

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/514224.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

给力!斩获 GitHub 14000 Star,两周创办开源公司获数百万美元融资

上世纪 90 年代初,21 岁大学生 Linus Torvalds 开源 Linux 操作系统,自此掀起全球开源浪潮。随后“中国 Linux 第一人”宫敏博士用手提肩背的方式将 20 盒磁带背回中国,磁带里装着 80G 容量的自由软件,组建起中国第一个自由软件库…

函数计算镜像加速:从分钟到秒的跨越

简介: 函数计算 FC 正式发布容器镜像加速,通过按需读取和更高效的解压技术在不同场景下加速 50%-80%,即使 GB 级别的镜像也可以在几秒内完成端到端启动。 FaaS 和容器 容器镜像因其颠覆式创新成为云原生时代应用部署格式的事实标准。头部云厂…

阿里云CDN产品经理陈章炜:边缘创新技术和落地实践

简介: CDN除了加速外,不断被赋予更多价值。在阿里云CDN推出的《极速奔跑吧 2021》首场直播中,阿里云架构师和产品经理不仅对近期阿里云发布的CDN产品最佳实践图进行了详细解读,还对CDN产品和客户的场景如何更高效地匹配、形成最优…

极狐GitLab:从硅谷到中国,远程办公背后的挑战与创新

编辑 | 宋 慧 供稿 | 极狐(GitLab) 头图 | 付费下载于视觉中国 最近,海外的互联网巨头们纷纷开启了远程办公的政策,谷歌允许员工提出更换办公地点的要求或申请成为永久远程办公者,目前已经批准了近 8000 名员工在家办公…

E百科 | 基于MEC的边缘AI服务

简介: 阿里云边缘计算团队付哲解读5G下热门场景:边缘AI。作者:阿里云付哲,计算机科学与技术专业博士后,在流量检测、资源调度领域有深入研究,其论文《Astraea: Deploy AI Services at the Edge in Elegant …

网速dns怎么调快_怎么设置dns?教你快速解决网速慢的问题

体内惊人荒之力很的洪,设置速解速慢设置速解速慢了一但其大批企业高成中中隐藏优质长的,复活,一旦。特斯提高金拉2的第度为的产大量的资7年能投入了三季,教决网仅生0辆产了,理想并不其效果却,交付2辆只有实…

“凡尔赛”式晒校园生活?移动云 9.9 风暴手把手教你!

快开学了卧虎藏龙的校园当然也少不了“凡尔赛大师”看看普通版和进阶版的凡尔赛学霸学神们如何用最低调的话炫最高调的耀LETS GO!考/试/篇假/期/篇生/活/费/篇看完学霸与学神的凡尔赛较量除了羡慕他们能够凡尔赛的资本更重要的是了解到移动云校园套餐原来如!此&…

开源微服务运行时 Dapr 发布 1.0 版本

简介: Dapr 是 2019 年 10 月开源的分布式运行时。早在 Dapr 开源初期,阿里云就开始参与 Dapr 社区建设和代码开发,目前已有两位 Dapr 成员,是 Dapr 项目中除微软之外代码贡献最多的公司。作为 Dapr 项目的早期采用者,…

如何应用数据模型

简介: 数据模型对于常规的数据查询或填写数据提交,是否有使用场景或者价值?数据模型这条路走的是否有问题? 一 前言 Vmo 是我在 18 年发布的一个工具库,用于快速创建数据模型,当时我写了一篇文章《Vmo 前端…

一行代码,揭开 CPU 执行原理!

作者 | 轩辕之风O来源 | 编程宇宙技术计算机如何执行你的代码?知乎上有人提问:电脑怎样执行编程语言的?很多刚刚入坑的小白可能对此完全没有概念,或者模模糊糊知道个大概,我们写下的一行行代码,计算机到底是…

有赞 Flink 实时任务资源优化探索与实践

简介: 目前有赞实时计算平台对于 Flink 任务资源优化探索已经走出第一步。 随着 Flink K8s 化以及实时集群迁移完成,有赞越来越多的 Flink 实时任务运行在 K8s 集群上,Flink K8s 化提升了实时集群在大促时弹性扩缩容能力,更好的降…

mysql怎么看端口号_mysql端口号(怎么查看mysql的端口号)

mysql端口号(怎么查看mysql的端口号)2020-05-07 21:54:58共10个回答如何查看mysql的端口号1使用命令showglobalvariableslikeport;查看端口号2修改端口,编辑/etc/my.cnf文件,早期版本有可能是my.conf文件名,增加端口参数,并且设定端口,注意该端口未被使用,保存退出.总结:注意修…

Serverless 如何在阿里巴巴实现规模化落地?

简介: 2020 年,我们在 Serverless 底层基建上做了非常大的升级,比如计算升级到了第四代神龙架构,存储上升级到了盘古 2.0,网络上进入了百 G 洛神网络,整体升级之后性能提升两倍;BaaS 层面也进行…

php验证mysql内数据_MySQL中数据类型的验证_MySQL

CHARchar (M) M字符,长度是M*字符编码长度,M最大255。验证如下:mysql> create table t1(name char(256)) default charsetutf8;ERROR 1074 (42000): Column length too big for column name (max 255); use BLOB or TEXT insteadmysql>…

专访合一智芯杨桦:做AI芯片核心技术的底层设计师

核心IP设计是国产化芯片的关键,杨桦是这个细分领域的一名创业者。作为曾在威盛电子和ARM公司工作过的芯片领域的老将,他一直追寻的目标就是给“中国芯”最好的设计。 作者 | 王查娜 来源 | 中国高新网 深研AI芯片设计 杨桦本科毕业于北京航空航天大学…

Flink SQL 性能优化:multiple input 详解

简介: 在 Flink 1.12 中,针对目前 operator chaining 无法覆盖的场景,推出了 multiple input operator 与 source chaining 优化。该优化将消除 Flink 作业中大多数冗余 shuffle,进一步提高作业的执行效率。本文将以一个 SQL 作业…

Java异步非阻塞编程的几种方式

简介: Java异步非阻塞编程的几种方式 一、 从一个同步的Http调用说起 一个很简单的业务逻辑,其他后端服务提供了一个接口,我们需要通过接口调用,获取到响应的数据。 逆地理接口:通过经纬度获取这个经纬度所在的省市区…

张一鸣 90 亿购得元宇宙入场券,谁将是头号玩家?

整理 | 禾木木 出品 | CSDN云计算(ID:CSDNcloud) VR 技术不断发展,虚拟网络世界“元宇宙”的概念也愈加火热,VR 已经不再局限于游戏与影视,它将作为降本增效的工具服务于更多行业领域。 8月29日&#xf…

前端开发:如何正确地跨端?

简介: 面对多种多样的跨端诉求,有哪些跨端方案?跨端的本质是什么?作为业务技术开发者,应该怎么做?本文分享阿里巴巴ICBU技术部在跨端开发上的一些思考,介绍了当前主流的跨端方案,以及…

mysql 创建表check如何使用_MySQL怎么使用check约束

在数据库中,CHECK 约束是指约束表中某一个或者某些列中可接受的数据值或者数据格式(用于限制列中的值的范围)。在一些情况下,我们需要字段在指定范围的输入,例如:性别只能输入 男或者女,余额只能大于0等条件&#xff0…