0%

从五种架构风格推导出HTTP的REST架构

在分布式的Web架构中呢,有5类架构风格。那么什么叫架构风格呢?我们在日常编程中可能会有习惯用法,再高一级在面向对象语言中呢,可能会有设计模式,那么再往上更大粒度的抽象我们可以用到架构。而架构风格是指某一类架构它们具有相同的或者说类似的一些约束,我们把它归纳为一类架构风格。那么我们rest架构,也就是HTTP设计所遵循的这样的架构会使用到我们下面的,或者说参考我们下列5类架构风格中的其中一些架构。

那么这5类架构风格呢,主要包括:

  1. 数据流风格 Data-flow Styles(协议的分层,nginx)
    • 优点:简单性、可进化性、可扩展性、可配置性、可重用性
  2. 复制风格 Replication Styles
    • 优点:用户可察觉的性能、可伸缩性、网络效率、可靠性也可以得到提升
  3. 分层风格 Hierarchical Styles
    • 优点:简单性、可进化性、可伸缩性
  4. 移动代码风格 Mobile Code Styles
    • 优点:可移植性、可扩展性、网络效率
  5. 点对点风格 Peer-to-Peer Styles
    • 优点:可进化性、可重用性、可扩展性、可配置性

数据流风格Data-flow Styles

  • 管道和过滤器Pipe And Filter,PF
    • 每个Filter都有输入端和输出端,只能从输入端读取数据,处理后再从输出端产生数据(协议,TCP-ip-数据链路层协议,只能从输入端到输出端)
  • 统一接口的管道与过滤器 Uniform Pipe And Filter, UPF
    • 在PF上增加了统一接口的约束,所有Filter过滤器必须具备同样的接口

主要这种数据流风格会对简单性上有所体现,特别是UPF以后简单性会有很大的提升,我们每一个模块每一个Filter都可以独自的去升级进化不影响。那么我们再增加一个新的功能,比如说增加一个新的协议层,或者说nginx增加一个新的模块,都是很容易的,所以可扩展性也是非常好的。那么可配置性也是一样的,我们可以通过配置文件灵活的去增加我们的Filter或者说我们的协议层级,而在我们的可重用性上面也是非常好的。每一个Filter我们会独立的拿下来以后给新的这样的一种架构去使用。

复制风格Replication Styles

  • 复制仓库Replicated Repository,RR
    • 多个进程提供相同的服务,通过反向代理对外提供集中服务(MySQL冷热备份,Web app同时提供很多服务、使用nginx反向代理)
  • 缓存$
    • RR的变体,通过复制请求的结果,为后续请求复用

复制仓库与缓存这两种架构,对于用户可察觉的网络性能,RR和$风格因为都会对用户能够觉察到的性能有一个提升。缓存风格呢,因为直接减少了网络的传输量,所以网络效率会更高一些,那scalability呢,可伸缩性,因为有很多可以复制的进程或者可以复制的数据,也会导致我们scalability更好。简单性上,缓存风格也会表现更好一些。因为我有多个进程多个服务,所以可靠性上也会更好一些。

分层风格Hierarchical Styles

  • 客户端服务器Client-Server, CS(HTTP)
    • 由Client触发请求,Server监听到请求后产生响应,Client一直等待收到响应后,会话结束
    • 分离关注点隐藏细节,良好的简单性、可伸缩性、可进化性(Server只关注资源的响应的生成,资源的管理,Client就关注于网络和结果可视化的渲染。向对方都隐藏了各自的细节,所以它们的简单性相对比较好,我们只关注中间的协议,而不关注可视化或者说数据库的管理。可伸缩性:比如Server在不停地增加更多的服务的节点,我们就可以为client提供更高可用性的服务。可进化性,意味着我们client和server都可以独立的进行进展)
  • 分层系统Layered System, LS
    • 每一层为其上的层服务,并使用在其之下的层所提供的服务,例如TCP/IP,OSI
  • 分层客户端服务器Layered Client-Server, LCS
    • LS+CS,例如正向代理和反向代理,从空间上分为外部层与内部层(正向代理,客户端和整个网络环境分离,反向代理把企业内网和整个企业外面的Internet网络进行了分层
  • 无状态、客户端服务器Client-Stateless-Server CSS
    • 基于CS,服务器上不允许有session state会话状态
    • 提升了可见性、可伸缩性、可靠性,但重复数据导致降低网络性能(HTTP 2.0的很多升级都体现在这几个方面,HTTP2.0中不希望重复的传递HTTP的头部,因为HTTP的头部特别是Cookie占用了网络资源,就是HTTP2.0已经做不到无状态了,所以它的重复数据相对比较少,网络性能更高,但是可见性、可伸缩性、可靠性上,相对较差一些。
  • 缓存、无状态、客户端服务器Client-Cache-Stateless-Server-C$SS
    • 提升性能(因为有重复数据,因为反复传递相同的header,环节可能导致的问题)
  • 分层、缓存、无状态、客户端服务器Layered-Client-Cache-Stateless-Server, LC$SS

client connector, client+cache, server connector, server+cache

  • 远程会话Remote Session, RS
    • CS变体,服务器保存Application State应用状态(FTP)
    • 可伸缩性(不可能任意扩充服务器而对客户端没有影响)、可见性差(因为我单独的抓取一个报文,分析一个报文是没有办法得到完整的请求信息的)
  • 远程数据访问Remote Data Access, RDA
    • CS变体,Application state应用状态同时分布在客户端与服务器(SQL访问,因为我们的查询集可能包含几百万条数据,所以我们必须要用到游标cursor,反复的一页一页地获取数据,也就是使得我们的客户端保存了一个应用的状态,我当前查询到第几页,而服务器端也需要为游标来保存这样的相应的数据)
    • 巨大的数据集有可能通过迭代而减少整个数据集
    • 简单性、可伸缩性差(我们传统的关系型数据库很少能够支持这种高可用性,基于数据仓库的多个热备份的分布式架构,是很难达到的)

由服务器来保存客户端的架构都会导致scalability很差,所以我们HTTP协议所依赖的Rest架构不使用这两种方式。特别是加入分层,加入CS架构以后,scalability是非常优秀的,简单性也是因为我们加入分层统一无状态以后,得到了很大的提升。可进化性因为所有基于client server这种分离关注点的情况下,我们的可进化性都是比较优秀的。而在可重复使用上,特别是基于分层属性后,都会有很大的一个提升。而在可见性上,因为我加入了一个stateless,无状态,无状态的情况下每一条请求都携带了全部的信息,所以我的可见性会更好。那么可移植性,也是基于分层以后可移植性有了很大的提升。可靠性呢,因为我们有了无状态有了缓存以后,我们的可靠性也得到了提升。

移动代码风格Mobile Code Styles

(表示实际程序要执行的那个代码是可以任意的从客户端到服务器端移动的)

  • 虚拟机Virtual Machibe, VM

    • 分离指令与实现(公有云、基于KVM,Java的虚拟机)
  • 远程求值Remote Evaluation, REV

    • 基于CS的VM,将代码发送至服务器执行
  • 按需代码Code on Demand,COD

    • 服务器在响应中发回处理代码,在客户端执行(JS脚本)
    • 优秀的可扩展性和可配置性,提升用户可察觉性能和网络效率
  • 分层、按需代码、缓存、无状态、客户端服务器

    Layered-Code-on-Demand-Client-Cache-Stateless-Server, LCODC$SS

    • LC$SS+COD
  • 移动代理Mobile Agent,MA

    • 相当于REV+COD

REV的安全性风险太大

统一接口的LC$SS+COD的架构

用户可察觉的网络性能,网络性能,可伸缩性,可进化型,可扩展性,可配置性,可见性,可重用性

Peer-to-Peer Styles

  • Event-based Integration,EBI

    • 基于事件集成系统,如由类似kafka,Rabbit MQ这样的消息系统+分发订阅来消除耦合
    • 优秀的可重用性、可扩展性、可进化性
    • 缺乏可理解性
    • 由于消息广播等因素造成的消息风暴,可伸缩性差
  • Chiron-2,C2

    参见论文《A Component-and Message-Based Architectual Style for GUI Software

    • 相当于EBI+LCS,控制了消息的方向
  • Distruibuted Objects,DO

    • 组件结对交互
  • Brokered Distributed Object,BDO

    • 引入名字解析组件来简化DO,例如CORBA

风格演化到rest