本文是《Software Architecture Patterns》这本书的心得分享,总结5种当下流行的架构模式。
相比 Bob 大叔的 《The Clean Architecture》,软件架构模式这本书讲的实在,并且都是常见的架构模式。
(本来是写给架构师做架构决策的,我只略观一二)
让人一看有种,哦,那个啥啥框架不就是使用的这种模式么
的感觉。
Patterns include:
- Layered architecture (分层模式)
- Event-driven architecture (事件驱动,事件派发模式)
- Microkernel architecture (微内核模式)
- Microservices architecture (微服务模式)
- Space-based architecture (基于空间的模式)
以及不使用架构模式,或者使用反模式的代价(后期 bug 越来越多,迭代困难)。
原文很精彩,下面简单概括。(阅读本文需要一定时长的开发经验,客户端服务端框架的使用经验)
概述
应用程序缺乏合理的架构一般会导致程序过度耦合、容易被破坏、难以应对变化,同时很难有一个清晰的版本或者方向性。这样的结果是,如果你没有充分理解程序系统里每个组件和模块,就很难定义这个程序的结构特征。有关于程序的部署和维护的基本问题都难以回答,比如:程序架构是什么规模?应用程序有什么性能特点?应用程序有多容易应对变化?应用程序的部署特点是什么?架构是如何反应的?
架构模式帮助你定义应用程序的基本特征和行为。例如,一些架构模式会让程序自己自然而然地朝着具有良好伸缩性的方向发展,而其他架构模式会让程序朝着高度灵活的方向发展。
了解架构模式的优点和缺点是非常必要的,它帮助我们选择一个适合自己特定的业务需求和目标的的程序。
架构模式
分层架构模式
对程序员来说很常见一种情况是在没有合理的程序架构时就开始编程,没有一个清晰的和定义好的架构的时候,大多数开发者和架构师通常会使用标准式的传统分层架构模式(也被称为多层架构)——通过将源码模块分割为几个不同的层到不同的包中。
不幸的是,这种编码方式会导致一系列没有组织性的代码模块,这些模块缺乏明确的规则、职责和同其他模块之间的关联。这通常被称为架构大泥球。
这种架构是大多数Jave EE应用的实际标准,因此很多的架构师,设计师,还有程序员都知道它。(如 MVC)
分层架构中的每一层都着特定的角色和职能。
分层架构的一个突出特性是组件间关注点分离 (separation of concerns)。一个层中的组件只会处理本层的逻辑。比如说,展示层的组件只会处理展示逻辑,业务层中的组件只会去处理业务逻辑。多亏了组件分离,让我们更容易构造有效的角色和强力的模型。这样应用变的更好开发,测试,管理和维护。
层隔离带来的好处是变化的影响只限于当前层次,不会紧耦合。(哪怕把某一层的实现技术给换了,只要接触接口不换,没问题的)但是逐层访问带来了效率上的损失(试想请求只是简单的穿过层,而不必做处理的情况),而且扩展困难,比如你想扩展一个 Service 层做权限控制,怎么办?
一般情况下,只能逐层访问,不能越级;即每层都是封闭的,但也不排除需要越级访问的可能,这个时候只能开放:
以前在学习 JSP 技术的时候,碰到的最多的恐怕就是:
(这里的 POJO 负责调整数据格式, 纯粹的 数据bean)
最后总结:
分层架构是一个很可靠的架构模式。它适合大多数的应用。
项目控制得益于封闭的隔离(不能跨级访问),但是如果有很多请求都只是简单的穿层而不需要处理,那么可以适当开放一下。
事件驱动
写完之后,发现其实 Qt 是这方面的集大成者。(仔细想Qt的那个 event, eventFilter)
一谈到事件驱动,我就想到 select, poll, epoll那些监听然后回调操作。
实际上事件驱动是一种更加抽象的东西,不仅仅是异步分发事件,还涉及到是否采用队列,通知是否包含处理回调,还是简单的异步通知给回调对象,让它处理。这就好像是 windows 的 iocp, 以及类 unix 的 epoll 的区别。
总之,异步就OK,异步性能高啊。
还是按照作者的思路来说:
- 核心中介全权负责包办 (mediator) – 集权
- 核心这里负责了一个队列event queue,不用分拣, 也不用管什么事件,派发给具体的处理对象,他们再根据事件类型处理
- 或者并行处理: 当你回调给我,我按照类型给你放入具体的事件队列,然后不同的事件对象处理相应事件队列的任务
- 代理分发给具体对象 (broker) – 分权 (各环节一个队列,上一环节没有走完,则进入不了下一环节)
- 一旦某个事件处理器将事件传递给另一个事件处理器,那么这个事件处理器不会与该事件的后续处理产生任何联系。
Mediator:
如果是非并行,那么肯定需要一个集中队列(并且第一种没有分拣,所以 processer 里还有不同 module);如果是并行,那么维护一个二级”事件类型队列”即可。
Broker:
微内核
微内核架构主要需要考虑两个方面: 核心系统和插件模块。应用逻辑被划分为独立的插件模块和核心系统,这样就提供良好的可扩展性、灵活性,应用的新特性和自定义处理逻辑也会被隔离。
微内核可以独立运行,并且如果内核足够强大,可以支持很多插件。(插件之间最好不要有依赖)
插件模块可以通过多种方式连接到核心系统,包括OSGi ( open service gateway initiative )、消息机制、web服务或者直接点对点的绑定 ( 比如对象实例化,即依赖注入 )。你使用的连接类型取决于你构建的应用类型和你的特殊需求(比如单机部署还是分布式部署)。微内核架构本身没有指定任何的实现方式,唯一的规定就是插件模块之间不要产生依赖。
缺点是,扩展性一般,并且随着插件的增多,运行效率一般。
(例如: eclipse)
微服务架构
微服务架构模式作为替代单体应用和面向服务架构的一个可行的选择,多个应用一个接口。
它的架构大致上是这样的:
要理解这种模式,最重要的概念就是服务组件(service component)。不要考虑微服务架构内部的服务,而最好是考虑服务组件,从粒度上讲它可以小到单一的模块,或者大至一个应用程序。服务组件包含一个或多个模块(如Java类),这些模块可以提供一个单一功能(如,为特定的城市或城镇提供天气情况),或也可以作为一个大型商业应用的一个独立部分(如,股票交易布局或测定汽车保险的费率)。
这些组件可能是远程服务或者本地服务,常见的是远程服务: JMS, AMQP, REST, SOAP, RMI, RPC。
根据拓扑结构不同,有演变出3个有意思的模式:
- 基于 REST API (适用于网站, web api)–简单的 api 层
- 基于 REST 应用 (这个是背后对应着业务组件,胖客户端)
- 集中式消息拓扑结构 (有先进的排队机制、异步消息传递、监控、错误处理和更好的负载均衡和可扩展性)
其中最后一种最优,不管后端有多强大的服务进程,端,服务器;都不应该让用户API直接操作,而是放入服务队列,异步处理。
换言之,你不能让client直接访问真实对象,要弄个代理对象(代理集群,代理联盟)给它。
空间模型(分布式)
这种架构纯粹的就是分布式架构了,也是相对来说最复杂的架构了。
这个架构中有两个主要的模块:处理单元 和 虚拟化中间件。下图展示了这个架构和里面的主要模块:
- 处理单元包含了应用模块(或者部分的应用模块)。具体来说就是包含了web组件以及后台业务逻辑。(小型的web应用可能会部署到单一的处理单元,而大型一些的应用会将应用的不同功能模块部署到不同的处理单元中)典型的处理单元包括应用模块,以及保存在内存的数据框架和为应用失败时准备的异步数据持久化模块。
- 虚拟化中间件负责保护自身以及通信。它包含用于数据同步和处理请求的模块,以及通信框架,数据框架,处理框架和部署管理器。
此外还要涉及,组件间如何合作,虚拟化中间件监控组件是否可用,组件和虚拟化中间件之间如何做到数据同步。
(分布式计算这部分内容太多了,不展开了)
小结
几种架构中,分层,事件派发,微内核,微服务都是很好理解,分布式架构的困难应该在计算,消息通信和同步上。
只当是老架构师写了本书,给我开开眼,收获颇丰。
分享
最后分享一个有趣的漫画 《架构师成长之路》,但主要跟存储,分布式相关。
Merlin 2018.2 真正谈清楚还需要大篇幅,这里只是把理解到的部分内容写出来(没有很详细展开)