职业生涯规划Java架构技术进阶Java

授之于渔,用“保险索赔”详解Dubbo原理,微内核架构一看就懂了

2020-05-21  本文已影响0人  Java余笙

授人以鱼,不如授之以渔,其实这句话说的不只是如何教人。

从另一个角度看这句话,我们在学一样东西的时候,要找到这样东西的”渔“是什么。

对于一项技术来说,它背后的设计思想,就是学习它的”渔“,对于 Dubbo,”渔“,是微内核架构。

首先,我们以「保险索赔」为例,了解下什么是微内核架构。

保险索赔

保险索赔的规则往往很复杂,不同保险产品、不同地区的索赔规则可能都不一样。

举个例子,假设在纽约州(NY),汽车挡风玻璃被岩石击碎,是可以索赔的,但是在加利福尼亚州(CA)则不行。这时候如果直接把这个逻辑写到代码里去,就是这样:

if (在纽约) {   if (被岩石击碎)  {       // 索赔...   }} else if (在加利福尼亚) {    if (被岩石击碎)  {       // 不索赔...    }}

而且保险规则可不只这一条,到时候写出来就是这样:

if (在纽约) {   if (被岩石击碎)  {       // 索赔...   }   if (被陨石击碎)  {       // 索赔...   }   if (被流星击碎)  {       // 索赔...   }   // more and more...} else if (在加利福尼亚) {    if (被岩石击碎)  {       // 不索赔...    }    if (被陨石击碎)  {       // 不索赔...    }    if (被流星击碎)  {       // 不索赔...    }    // more and more...}

可以看到,我们把索赔规则的代码耦合到了索赔的核心系统中:

这会带来两个问题:

于是我们把这些规则抽取出来,有个专门的地方去管理这些规则,简单说,就是「解耦」:

这样就解决了「耦合度高」的问题,但其实解耦的还不够彻底。

不同州的规则还是放到一起的,而我们在索赔处理的时候,每次只需要加载一个州的索赔规则,不存在既需要纽约州的规则,又需要加州规则的情况:

授之于渔,用“保险索赔”详解Dubbo原理,微内核架构一看就懂了

另外,如果后面新来了一个州,想接入索赔系统,那么如何让这个州,在不影响其他州的情况下,配置自己的索赔规则?

于是有了这样一套保险索赔的「微内核架构」:

简单说就是,这套系统分两个模块:

1、中间的核心模块

处理保险索赔的基本业务逻辑;

2、保险规则

由每个州自己去实现,做成插件,可以被单独加载和移除,不影响核心系统和其他插件。

了解完了保险索赔系统的微内核实现,我们再来看看微内核架构,到底是什么。

什么是微内核架构

Oreilly 对于微内核架构的定义是这样的(纯英文,大家要再三细品):

The microkernel architecture pattern consists of two types of architecture components: a core system and plug-in modules.

Application logic is divided between independent plug-in modules and the basic core system, providing extensibility, flexibility, and isolation of application features and custom processing logic.

简单说,就是微内核架构包含两个组件:核心系统(core system)和插件模块(plug-in modules),目的是为了扩展性、灵活性和隔离性。

核心系统和插件模块又都有什么职责呢?

The core system of the microkernel architecture pattern traditionally contains only the minimal functionality required to make the system operational.

The plug-in modules are stand-alone, independent components that contain specialized processing, additional features, and custom code that is meant to enhance or extend the core system to produce additional business capabilities.

核心系统只包含让系统可以运作的最小功能,有点像 MVP(Minimum Viable Product ,最小可用产品)。

而插件模块,则包含一些特殊处理逻辑、额外的功能、自定义代码,用于强化和扩展核心系统,提供更多的业务能力。

这么讲还是比较抽象,所以,接下来,进入主题,来看看 Dubbo 这个 RPC 框架,是如何基于微内核架构进行设计的。

什么是 RPC 系统的 core?

Dubbo 在本质上是在解决如何进行远程调用(rpc)的问题,通常一个 rpc 系统都长这个样子:

但是这些都是一个 rpc 系统所必须的吗?

能不能去掉哪个模块后,依然可以进行 rpc 调用?

相信大多数人都可以发现,stub 层是可以去掉的,去掉后,无非你就没法再进行透明式调用罢了。

还有吗?还有其他哪个模块也可以去掉吗?

我们来看一个极简的 rpc 调用:

在这个例子里,服务提供方,和服务消费方,是位于同一块内存的:

大道至简,当我们把 rpc 这个模型进行简化后,会发现其实这样就足够了:

其实这也是 Dubbo 里 inJVM 协议的实现原理。

当然实际使用中,我们不可能只使用内存调用的 rpc,举这个例子,其实是为了下面介绍 Dubbo 的内核。

什么是 Dubbo 的 core?

我们从系统的角度,看看 Dubbo 的整体设计图:

这个是一种传统的分层视角,每一层都有自己要解决的问题,用 DDD 的话来说,就是每个域都有自己的问题空间:

按照这个视角来看,其实每一层都有自己的 core,每一层都支持通过 SPI 的方式,来实现扩展。

但如果我们换个视角来看,之前说过,Dubbo 本质上是为了解决 rpc 的问题,那么其实我们只需要 protocol 层就足够了:

我们也不必再用传统的分层架构来看,而是换一个视角:

这个叫「六边形架构」(Hexagonal Architecture),也叫「端口-适配器架构」(Ports and Adapters Architecture),这里就不展开细讲了,有兴趣的同学可以谷歌下。

两种视角的不同就在于,传统分层视角没有突出核心和重点,你看不出哪一层是必须的,哪一层是整个架构的起源,而六边形架构,则一目了然。

对于 Dubbo 来说,只有 Protocol 层是核心,是必须的:

那么 Protocol 层都做了什么呢,为什么有了它就可以实现一次 rpc 调用?

Protocol 层如何实现 rpc 调用?

Protocol 层,其实就是上面提到的,一个最简化的 rpc 模型:

三个角色:

很明显,核心角色是 protocol,比如你采用 injvm 协议,那就会生成 InjvmInvoker 和 InjvmExporter:

而如果你采用的是 dubbo 协议,则会生成 DubboInvoker 和 DubboExporter:

仔细看代码,你会发现,dubbo 协议的 refer 方法,会把 invoker 放进一个 invokers 集合里,injvm 协议的 refer 方法,则直接 new 一个 invoker 后就返回了,说明前者是有可能存在多个服务提供者的,而后者只会有一个。

而这些细节上的差异,追溯到根源,就是你用了什么样的协议(protocol)。

在 RPC 中,Protocol 是核心层,也就是只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 调用。—— from Dubbo 框架设计

微内核架构的其他使用

除了上面提到的保险索赔、Dubbo,微内核架构还被用到很多地方。

其实微内核架构的起源,是操作系统:

左边是 Microkernel,右边是与之对应的 Monolithic Kernel,前者只提供最最基础的操作系统能力,而把更多的能力开放给外界来提供,而后者则倾向于提供一个大而全的操作系统。

这里不展开讲,大家可以前往维基百科了解下。

后来,这种思想逐渐被演变成一种架构设计模式,于是有了「微内核架构」。

它被用在了许多客户端应用,像 Chrome 浏览器:

Eclipse 编辑器:

Chrome 核心就是一个浏览器,用来浏览网页。你可以给它添加各种各样的插件,像翻译插件、广告屏蔽插件等等;而对于第三方开发者,则可以给它开发各种插件。

Eclipse 也一样,核心就是一个编辑器,和记事本没什么区别,给它添加各种各样的插件,像代码高亮、java 代码编译等等,就成了一个好用的开发工具;第三方开发者同样可以给它开发各种插件。

之后它又被进一步用在了一些软件框架、业务系统上,比如今天讲到的 Dubbo 和保险索赔系统。

甚至在之后的「六边形架构」、DDD 上,都可以看到「微内核架构」的影子,这两种设计思想被大量用到各种框架、中间件的设计上,比如有赞的 MAXIM 全链路压测引擎:

你可以用一两句话概况这种思想,比如:开闭原则、模板模式、把不变的和变化的隔离等等,但是仅仅通过这种标签式的、高浓缩的、刻板印象的语言就来概况它,未免还是太过缺乏细节和激情了。

微内核架构的优缺点

作为一种架构设计的模式,通常都会考虑这些问题:

微内核架构也不例外,它的优点很明显:

扩展性:高

健壮性:高

易部署性:高

可测试性:高

缺点也有:

可伸缩性:低

开发难度:高

开发难度高这一点,从 Dubbo 的扩展点重构历程就可以看出来,其实一开始 Dubbo 并不是我们看到的分层架构,而是一步一步演进过来的,每一步都包含这背后开发人员的卧薪尝胆和绞尽脑汁:

最后

授人以鱼不如授人以渔,其实这句古话是有出处的:

临河而羡鱼,不如归家织网。—— 《淮南子·说林训》

人类历史上迸发过许多璀璨的思想,就像微内核架构其实来源于操作系统的微内核。

我们在回过头去看的时候,可以嘲笑他们有些观念落伍了,但不要忘了一件事,慢一点,再慢一点,不要错过一些可能闪耀出来的那点星光。

参考:

来源于柳树的絮叨叨 ,作者靠发型吃饭的柳树

上一篇下一篇

猜你喜欢

热点阅读