Rest Notes-基于网络应用的架构风格

摘要: 上章节划定了我们要讨论的范围是基于网络应用的架构,接下来对基于网络应用的常见架构风格进行了调查,并针对每个风格进行多方面的评估

正文:

基于网络应用的架构风格

数据流风格

风格 继承 网络性能 用户感知性能 简单性 可进化性 可配置性 可扩展性 可重用性 可见性
PF ± + + + + +
UPF PF - ± ++ + ++ + ++ +

(-)是消极影响,(+)是积极影响,(±)是表示影响的性质取决于问题领域的某个方面,(空)是没有约束

管道和过滤器(Pipe and Filter,PF)

每个过滤器(组件)从输入端读取数据流,在输出端产出数据流,通常会对输入数据流应用一种转换并增量的处理它们

缺点:

  • 长管道会增加延迟
  • 不能增量处理只能批量顺序处理,降低用户感知性能

统一管道和过滤器(Uniform Pipe and Filter,UPF)

在PF风格的基础上增加了必须具有相同接口的约束

如Unix操作系统中,其中过滤器进程具有一个字符输入流(stdin)和两个字符输出数据流(stdout和siderr)组成的接口

通过限定使用这个接口就可以排列组合独立的过滤器形成新的应用,理解过滤器的运转也会变得简单

缺点:

  • 当数据需要转换时候这个约束可能会降低网络性能

复制风格

风格 继承 用户感知的性能 效率 可伸缩性 简单性 可靠性
RR ++ + +
$ RR + + + +

复制仓库(Replicated Repository,RR)

利用多个进程提供相同的服务来改善数据的可访问性、可伸缩性,给客户端制造出只有一个集中服务的幻觉

优点:

  • 改善了用户感知的性能
    • 减少处理正常请求的延迟
    • 在主服务器故障或断网时候支持离线操作

缺点:

  • 复制所导致的复杂性

缓存(Cache,$)

缓存风格继承复制仓库风格,复制个别请求结果以便后面的请求复用

优点:

  • 缓存风格实现起来要更容易

缺点:

  • 用户感知的性能层面上改善不大,因为会存在大量没有命中缓存的请求,离线操作也只会是历史数据

分层风格

风格 继承 网络性能 用户感知性能 效率 可伸缩性 简单性 可进化性 可重用性 可见性 可移植性 可靠性
CS + + +
LS - + + + +
L+CS CS+LS - ++ + ++ + +
CSS CS - ++ + + + +
CSS+$ CSS+$ - + + ++ + + + +
LC$SS LCS+C$SS - ± + +++ ++ ++ + + + +
RS CS + - + + -
RDA CS + - - + -

客户-服务器(Client-Server,CS)

这个是最常见的架构风格,服务端提供接口(服务),客户端通过连接器发送请求执行这个接口(服务),服务端收到后进行正常操作

分层-客户-服务器(Layered-Client-Server,LCS)

分层系统(Layered System,LS)是按照层次来组织的,下面一层给上面一层提供服务,底层则会隐藏细节;在基于网络的系统中(前文提到的讨论范围),分层系统仅限于与CS相结合,形成LCS风格

LCS是在CS的基础上添加了代理(proxy)组件和网关(gateway)组件,例如我们目前前端开发使用的转发代理和API网关,这样额外的工作为系统添加了多个层,从而实现例如LoadBlance和Security Check

优点:

  • 通过隐藏和封装的层级关系,减少了耦合,改善了可进化性和可重用性

缺点:

  • 增加了处理数据的开销和延迟
  • 降低了用户感知性能

客户-无状态-服务器(Client-Stateless-Server,CSS)

该风格强调的是在服务端不允许有会话状态(session state),所以客户端给服务端发的每个请求都必须包含理解(解析到)请求的必备信息,会话状态交给客户端保存

优点:

  • 可见性

    以前需要看很多请求数据才可以确定请求的全部性质,现在看一个就行啦

  • 可靠性

    使故障的恢复更简单(无状态嘛)

  • 可伸缩性

    不保存多个请求的状态

缺点:

  • 每次请求都需要添加类似重复的数据
  • 降低网络性能,增大了交互的开销

客户-缓存-无状态-服务器(Client-Cache-Stateless-Server,CSS)

在CSS风格基础上增加了缓存风格,在客户端与服务端中间斡旋,重用历史的请求响应

优点:

  • 减少了一些交互,从而提高效率和用户感知性能

远程会话(Remote Session,RS)

该风格属于CS的一种变体,试图将客户端的复杂性最小化,可重用性(客户端)最大化,可以理解为“客户端的分布式会话”

优点:

  • 集中维护服务端接口更加容易
  • 利用会话上下文提高效率

缺点:

  • 减低了服务端的可伸缩性(毕竟需要保存状态,这点和无状态刚好是反的)
  • 降低了交互的可见性

远程数据访问(Remote Data Access,RDA)

该风格是CS的一种变体,将应用状态分布在客户端和服务端上,如客户端发送一个查询格式(sql或者自定义查询参数)给服务端,服务端执行这个查询,返回一个结果集,客户端可以拿到结果集进行数据筛选或拼接

有点类似在某险看到的数据服务,提供查询接口,根据自定义参数返回想要的数据

优点:

  • 提高了可见性(sql或约定好的参数规则)
  • 服务端可以进行数据的筛选,避免巨结果集在网络的传输

缺点:

  • 降低了服务端的可伸缩性
  • 部分的故障会导致可靠性的损失

移动代码风格

风格 继承 网络性能 用户感知的性能 效率 可伸缩性 简单性 可进化性 可扩展性 可定制性 可配置性 可重用性 可见性 可移植性 可靠性
VM ± + - +
REV CS+VM + - ± + + - + -
COD CS+VM + + + ± + + -

虚拟机(Virtual Machine,VM)

所有的移动代码都需要以某种方式来执行,这正是是虚拟机风格,虚拟机通常被当做某些语言的引擎,如JVM

优点:

  • 改善了可扩展性(指令和实现的分离,如JVM的Indy指令)

缺点:

  • 明显会降低了可见性、简单性

远程求值(Remote Evaluation,REV)

顾名思义,类似我们在一些开源组件看到的GLUE模式,或者说Web IDE这种,客户端将需要执行的代码发到服务端,服务端进行执行

按需代码(Code on Demand,COD)

该风格与上面的REV核心方向是相反的,由客户端访问服务端拿到想要的代码在客户端本地执行

这种风格在做流程自动化机器人有用到,访问服务端接口拿到动态脚本,客户端这边执行自动化脚本实现页面自动化操作

点对点(Peer-to-Peer)

风格 继承 网络性能 用户感知的性能 效率 可伸缩性 简单性 可进化性 可扩展性 可配置性 可重用性 可见性 可移植性 可靠性
EBI + ± + + + + - -
C2 EBI+LCS - + + ++ + + ++ ± + ±

基于事件的集成(Event-based Integration,EBI)

该风格也被称为隐式调用风格或者事件系统风格,通过消除了解连接器接口的标识信息的必要性,降低了组件之间的耦合

组件调用是通过发布事件或者广播,由系统本身来调用订阅该事件的组件,基于事件的这种风格为可扩展性、可重用性和可进化性(这些架构属性在第二篇基于网络的架构有详细介绍)提供了强有力的支持

缺点:

  • 事件风暴(可伸缩性问题)
  • 缺乏可理解性
  • 不适合交换大粒度的数据

C2

C2风格是对上面EBI的一个加强,通过增加分层-客户-服务器(LCS)风格来达到支持大粒度的重用和解决了可伸缩问题

异步通知消息向下传送,异步请求消息向上传送