软件架构:5种你应该知道的模式

Singleton(单例模式)、仓储模式(repository)、工厂模式(factory)、建造者模式(builder)、装饰模式(decorator)……大概每一个上课听讲的程序员都不会陌生——软件的设计模式为咱们提供了针对现有的、重复出现的问题以可靠的解决方案。git

在软件架构方面一样存在相似的机制,通用的、可重用的解决方案在给定上下文中的软件体系结构中常常出现的问题。不一样的软件架构模式各有千秋,如下是目前较为主流的5种软件架构模式。程序员

分层模式(Layered Pattern)

分层模式大概是最知名的软件架构模式之一,有大量的开发者使用,但并不知道它的名字。分层模式将代码拆分为“层”,每一个层都有必定的责任,并为更高“层”服务。github

分层模式并无规定层的数量,但一般会有如下结构:数据库

  • 表现层 / UI层
  • 应用层
  • 业务/域(domain)层
  • 持久/数据访问层
  • 数据库层

分层模式的想法是用户经过执行某些动做(例如点击按钮)在表现层启动一段代码。随后,表现层调用应用层、进入业务层,最后持久层将全部内容存储在数据库中。简单来讲,分层模式中的高层调用并依赖低层。设计模式

根据应用复杂程度,咱们会看到不少相应的变体。例如某些应用会省略应用层,而某些应用会添加缓存层,甚至会出现两层合一的状况。缓存

层责任

如上所述,每层有每层的责任。表现层包含应用的图形设计和处理交互的代码。理论上来说,咱们不该该在这一层添加任何与user interface无关的逻辑。服务器

业务层是放置特定业务问题模型和逻辑的地方。微信

应用层位于业务层和和表现层之间。一方面为表现层提供业务层抽象,另外一方面为应用层提供放置某些不适合放置于业务层或表现层的某些协调逻辑。架构

持久层包含访问数据库层的代码,而数据库层是底层数据库技术,例如SQL Server、MongoDB。持久层是用于操做数据库的代码集:SQL语句、链接详情等。框架

优点

  • 大多数开发者都很熟悉
  • 一种用于编写组织良好而且可测试应用的简单方法

劣势

  • 分层模式每每会致使应用的“一体化”并使之变得难以拆分
  • 开发者每每会发现本身编写了大量的代码来传递不一样的层,而没有在这些层里添加任何值。若是咱们作的只是编写一个简单的CRUD应用,分层模式可能有点过度了。

适用于

  • 标准的、不只仅用于完成CRUD操做的业务线(line-of-business)应用

微内核模式(Microkernel)

当应用程序有一组核心职责和一组可互换的部件时,微内核模式(或插件模式)很是有用。微内核将提供应用程序的入口点和通常流程,而不须要真正了解不一样的插件在作什么。

例如任务调度,微内核能够包含全部的调度和触发逻辑,而插件负责特定的任务。只要插件遵循特定的API,微内核就能够出发它们,而不须要了解实现的细节。

另外一个例子是工做流。工做流的实现包含诸如不一样步骤的顺序、评估步骤的结果、决定下一步的内容等概念,步骤的的具体实现对于工做流的核心代码并不重要。

优点

  • 灵活性 & 可扩展性
  • 某些实现容许咱们在应用运行时添加插件
  • 微内核和插件能够由不一样团队开发

劣势

  • 难以肯定哪些东西属于微内核
  • 预约义的API可能不适合将来的插件

适用于

  • 从不一样来源获取数据、转换数据并写入不一样地方的应用
  • 工做流应用
  • 任务和做业调度应用

命令职责查询分离模式(CQRS)

CQRS是Command and Query Responsibility Segregation的缩写。这种模式的核心概念是应用具备彻底分离的读取操做和写入操做,这也意味着用于写操做(命令)的模型和读取(查询)不一样。此外,数据将存储在不一样的位置。在关系数据库中,意味着将存在用于命令模型的表和用于读取模型的表。一些实现甚至将不一样的模型存储在彻底不一样的数据库中,例如用于命令模型的SQL Server和用于读取模型的MongoDB。

CQRS模式一般和事件溯源(Event Sourcing)结合,下一小节会讲到。

CQRS如何工做?当用户执行操做,应用会向命令服务器发送命令。命令服务从命令数据库中检索所需的任何数据,进行必要的操做并将其存储回数据库中,而后它通知读取服务,以便更新读取模型。以下所示:

当应用须要向用户显示数据时,它能够经过调用读取服务来检索读取模型,以下所示:

优点

  • 命令模型专一于业务逻辑和验证,读取模型根据特定情境进行定制
  • 能够避免复杂的查询,让读取更高效

劣势

  • 保持命令和读取模型同步可能会让事情变得很复杂

适用于

  • 须要大量读取的应用
  • 有复杂域的应用

事件溯源模式(Event Sourcing)

这种模式不会将模型的当前状态存储在数据库中,而是将时间存储其中。所以,例如customer name发生变化时,该值不会存储在“name“列中,咱们会存储一个”NameChanged“事件。

当咱们须要检索模型时,咱们将检索其存储的全部事件并在新对象上从新应用,即rehydrating an object。

用EXCEL记帐来理解event sourcing会容易一些。当咱们添加支出时,咱们不需更改总值,而是增长一“行”,出现错误,也增长一“行”,最终利用EXCEL的公式自动计算出总数,而这里计算总数能够看做是读取模型。

您能够看到咱们在添加Invoice 201805时发生了错误。咱们添加了两条新行,而不是更改行,首先是一行取消错误的行,而后是新的正确行。这就是event sourcing的工做方式。你永远不会删除事件,由于它们无能否认地发生在过去。为了纠正状况,咱们添加了新事件。

另外,请注意咱们是如何获取总值的,它是上面单元格中全部值的总和。在Excel中,它会自动更新,所以咱们能够说它与其余单元格同步。这就是一个读取模型。

Event sourcing一般会与CQRS同时使用,由于rehydrating an object可能会对性能产生影响,尤为是当实例中存在大量事件时。快速读取模型能够显着改善应用的响应时间。

优点

  • 提供“开箱即用”的audit log,每一个事件即特定时间点上的特定操做

劣势

  • event sourcing有必定的限制要求,咱们不能直接经过数据库中的简单编辑来修复错误数据
  • 改变事件的结构比较复杂

适用于

  • 须要发布事件到外部系统的应用
  • CQRS应用
  • 有复杂域的应用
  • 须要数据修改audit log的应用

微服务模式(Microservices)

编写一组微服务实际上就是编写能够协同的多个应用。每一个微服务都有本身独特的责任,团队能够独立于其余微服务开发它们。他们之间惟一的依赖是通讯。当微服务相互通讯时,咱们必须确保它们之间发送的消息保持backwards-compatible(向后兼容)。这须要一些协调,特别是当不一样的团队负责不一样的微服务时。

以下图所示——

在上图中,应用调用一个中央API,将调用转发给正确的微服务。在此示例中,有为用户配置文件、库存、订单和付款提供单独的服务。咱们能够想象这是一个用户订购应用。单独的微服务也能够相互调用。例如,支付服务能够在支付成功时通知订单服务。而后,订单服务能够调用库存服务来调整库存。

没有明确规定微服务有多大。在前面的示例中,用户配置文件服务可能负责用户的用户名和密码等数据,也可能负责家庭地址、头像图像、收藏夹等,也能够选择将全部这些责任分红更小的微服务。

优点

  • 咱们能够单独编写、维护、部署微服务
  • 微服务架构容易扩展
  • 重写变得很容易,由于微服务之间松耦合

劣势

  • 实际上没有合适的工具平台,反而在最初编写结构良好的一体化应用,再拆分为微服务的办法实际上更容易。使用微服务,会产生许多额外的问题:通讯、协调,向后兼容、日志记录等。没有编写结构良好的总体结构的必要技能的团队可能很难编写一组良好的微服务。
  • 传统微服务架构可能会有多个失败点,查找问题可能会比较复杂

适用于

  • 某些组件被密集使用并须要扩展的应用
  • 为其余应用提供功能的应用
  • 一体化架构下很复杂的应用
  • 可以明肯定义bounded contexts的应用

总结

各类软件架构模式不少时候会结合起来使用,他们之间并无咱们想象得那么水火难容。换句话说,没有万能的软件架构模式,如何选择取决于咱们对于解决方案利弊的权衡。

关于Rainbond

当下,已经有很大一部分公司完成了单体架构向微服务架构的迁移改造,并在疲于应对大量微服务间通讯问题时,开始考虑采用Service Mesh微服务架构做为服务与服务直接通讯的透明化管理框架,以插件式的方式实现各类业务所需的高级管理功能。

而开源PaaS Rainbond提供了开箱即用的Service Mesh微服务架构,部署在Rainbond上的应用原生便是Service Mesh微服务架构应用。