阅读《clean architecture》也花了较长的时间,大致也了解到整洁的架构要做到以下两点:

  • well-isolated components:component是独立部署的最小单元,由一系列遵循SOLID原则的module按照REP、CCP、CEP原则组成。
  • dependency rule:低层的detail去依赖高层的police

但感觉并没有对架构设计给出可行的参考。

clean architecture 中的架构实例

《clean architecture》的第34章 “The Missing Chapter”(由 Simon Brown 编写)给出了一个具体的案例,用四种架构设计来实现一个 “online book store”。

package by layer

这是最常见的方案,从前往后分为:前端、后台(business logic)、持久化DB。

优点是:简单、容易上手,符合大多数公司的组织架构。

存在的问题:

  • 软件规模和复杂度增加时,三层架构就不够了,需要重新考虑拆分;
  • 分层架构体现不出business domain;

PACKAGE BY FEATURE

垂直切分方案,所有的java代码都放在一个package里面

好处在于凸显domain concept

PORTS AND ADAPTERS

clean architecture这本书推荐的方案, 外层依赖于内层的domain

PACKAGE BY COMPONENT

本章作者 Simon Brown 提出的方案,service-centric view,将所有相关的职责打包称一个粗粒度的Jar包

看起来类似现在微服务的部署方式

对于以上四种结构,依赖关系看起来是这样的
软件架构模式-LMLPHP

值得注意的是

  • 虚线箭头表示component之间的依赖关系
  • PORTS AND ADAPTERS这种架构更能体现domain(business logic),即接口命名为Orders而不是OrdersRepository

本章的作者最后还指出:++不管架构怎么设计,粗心的implementation都可能违背最初的设计;依赖编译器来保证架构的一以贯之,而不是自我约束或者事后检查。++

五种常见架构模式

看完了clean architecture后,在网上搜索架构设计相关的书籍,发现了software architecture patterns这本小册子,篇幅很短,称不上book,而是一个report。

software architecture patterns 指出缺乏架构设计的软件往往高度耦合,难以改变。因此,这本小册子的目标就是介绍常用架构模式的特点、优点、缺点,帮助我们针对特定的业务需求做出合适的选择。

Layered Architecture

分层架构也称为n-tire architecture,这是最为常见的一种架构模式,一般从前往后分为四层:presentation, business, persistence, and database。如下图所示:
软件架构模式-LMLPHP

分层架构一般是一个新系统的最佳首选,因为其完美匹配传统IT公司组织架构:一般的公司招人都是前端、后端、数据库。

分层架构的优点在于关注点隔离(separation of concerns),每一层做好自己这一层的职责,并向上一层提供服务即可,最为经典的案例就是七层网络模型,这有利于开发、测试、管理与维护。

分层架构中,需要注意的是两个概念:closed layeropen layer

closed layer的核心就是不要越层访问,比如在上图中,Presentation Layer就不应该跨国Business Layer直接去Persistence Layer访问数据。

closed layer保证了层隔离( layers of isolation),使得某一层的修改影响的范围尽可能小,比较可控。但closed layer有时候也会带来一个问题:architecture sinkhole anti pattern(污水池反模式),具体是指,为了查简单数据,层层转发请求。比如为了在展示层显示玩家的某个数据,需要通过业务层、再到持久化层、再到DB层;取到数据再一层层传递回来,在这个过程中,业务层并没有对数据有逻辑上的处理。

显示,污水池反模式冲击了closed layer的美好想法。如何衡量这种层层转发的请求是不是问题,可以参考80-20法则。

如果80%是附带逻辑的,那么就是ok的,但如果有80% 是 simple passthrough processing,那么就得考虑让某些layer open。比如在复杂的业务系统中, 经常会有一些可复用的逻辑,这个时候会抽取为通用的服务层(service layer)。如下图所示

软件架构模式-LMLPHP

open layer 、close layer的概念可以帮助理清楚架构和请求流程之间的关系,让架构师、程序员都清楚架构的边界(boundary)在哪里,重要的是,这个open-closed关系需要明确的文档化,不要随意打破,否则就会一团糟。

Event-Driven Architecture

从上述定义可以看出事件驱动架构的几个特点:分布式、异步、可伸缩。其核心是:高度解耦合、专一职责的事件处理单元(Event Processor)

事件驱动架构有两种常见拓扑结构: the mediator and the broker.

Mediator Topology

需要一个中心化(全局唯一)的协调单元,用于组织一个事件中的多个步骤,这些步骤中有些是可并行的,有些必须是顺序执行的,这就依赖Event Mediator的调度。如下图所示
软件架构模式-LMLPHP

Broker Topology
这种是没有中心的架构

如下图所示
软件架构模式-LMLPHP

事件驱动的好处在于,高度可伸缩、便于部署、整体性能较好(得益于某些事件的并发执行)。但由于其分布式异步的本性,其缺点也很明显:开发比较复杂、维护成本较高;而且很难支持事务,尤其是一个逻辑事件跨越多个processor的时候。

Microkernel Architecture

微内核架构又称之为插件式架构(plug-in architecture)。如下图所示:
软件架构模式-LMLPHP

微内核架构包含两部分组件

  • a core system
  • plug-in modules.

plug-in modules 是相互独立的组件,用于增加、扩展 core system 的功能。

这种架构非常适用于 product-based applications 即需要打包、下载、安装的应用,比如桌面应用。最经典的例子就是Eclipse编辑器,玩游戏的同学经常下载使用的MOD也可以看出插件。

微内核架构通常可以是其他架构的一部分,以实现特定部分的渐进式设计、增量开发

Microservices Architecture Pattern

微服务架构并不是为了解决新问题而发明的新架构,而是从分层架构的单体式应用和SOA(service-oriented architecture)演化而来。

微服务解决了分层架构潜在的成为单体式应用(Monolithic application)的问题:

同时,微服务还通过简化(泛化)服务的概念,消除编排需求,简化对服务组件的连接访问。从而避免了SOA的各种缺点:复杂、昂贵、重度、难以理解和开发。

微服务架构如下:
软件架构模式-LMLPHP

其核心是service component,这些服务组件相互解耦,易于独立开发、部署。服务组件的粒度是微服务架构中最难的挑战

  • 太大:失去了微服务架构的优势
  • 太小:导致需要编排,或者服务组件间的通信、事务。

而微服务架构相比SOA而言,其优势就在于避免依赖和编排 -- 编排引入大量的复杂工作。

对于单个请求 如果service之间还要通信,那么可能是就是粒度过小。解决办法:

  • 如果通信是为了访问数据:那么可以通过共享db解决
  • 如果通信是为了使用功能:那么可以考虑代码的冗余,虽然这违背了DRY原则。在clean architecture中也指出,component的自完备性有时候要高于代码复用。

Space-Based Architecture

基于空间的架构,其核心目标是解决由于数据库瓶颈导致的低伸缩性、低并发问题。

分层架构中,在用户规模激增的情况下,数据层的扩展往往会成为最后的瓶颈(相对而言,前端和业务逻辑都容易做成无状态,比较好水平扩展)。而基于空间的架构的核心是内存复制,根本上解决了这个问题。

架构如下:
软件架构模式-LMLPHP

其核心组件包括

  • processing unit,处理单元,其内部又包含一下组成
    • business logic
    • in-memory data grid
    • an optional asynchronous persistent store for failover
    • replication engine,用于同步数据修改
  • virtualized middleware
    • Messaging Grid: 监控processing unit可用性,路由客户端请求到processing unit
    • Data Grid: 核心,负责processingunit之间的数据同步,毫秒级同步?
    • Processing Grid: 可选组件,如果一个请求需要多个processing unit的服务,那么负责协调分发
    • Deployment Manager: 负责processing unit的按需启停

基于空间的架构很少见,而且从上面的核心组件描述来看的话,开发和维护应该都是比较负责的,由于是数据的同步这块。而且由于数据都保存在内存中,那么数据量就不能太大。

references

clean architecture

software architecture patterns

11-24 19:29