学习笔记-架构的演进之RESTful服务-2月day10

引言

RESTful 服务被认为是当前一种流行的远程服务访问风格,它与 RPC 在设计思想上差异的核心,是在于抽象的目标不一样:REST是面向资源的编程思想,RPC是面向过程的编程思想。

REST 与 RPC 作为主流的两种远程调用方式,虽然在使用范围上有重合之处,但是也并不能说REST解决了RPC中的疑难问题(分布式对象、提升调用效率、简化调用复杂性):

  • 对于分布式对象这一条线的应用,对于 REST 就可以说是毫无关系;
  • 而能够重视远程服务调用效率的应用场景,就基本上已经排除了 REST 应用得最多的供浏览器端消费的远程服务。因为以浏览器作为前端,对于传输协议、序列化器这两点都没有什么选择权,哪怕想要更高效率也有心无力。
  • 而在移动端、桌面端或者分布式服务端的节点之间通讯这一块,REST 虽然照样有宽阔的用武之地,只要支持 HTTP 就可以用于任何语言之间的交互,不过使用 REST 的前提是网络没有成为性能上的瓶颈。但是在需要追求传输效率的场景里,REST 提升传输效率的潜力有限,死磕 REST 又想要好的网络性能,一般不会有好的效果。
  • 对于追求简化调用的场景,我在前面提到的浏览器端就属于这一类的典型,在众多 RPC 里,也就 JSON-RPC 有机会与 REST 竞争,其他 RPC 协议与框架,哪怕是能够支持 HTTP 协议,哪怕提供了 JavaScript 版本的客户端(如 gRPC-Web),也只是具备前端使用的理论可行性,很少能看到有实际项目把它们真的用到浏览器上的。

理解REST

REST 概念的提出来自于罗伊·菲尔丁(Roy Fielding)在 2000 年发表的博士论文:《Architectural Styles and the Design of Network-based Software Architectures》(架构风格与网络的软件架构设计),并为这种编程架构风格命名为REST,即“表征状态转移”(Representational State Transfer)。
(理解REST,可以参照HTTP的概念)
HTTP 中使用的“超文本”一词,是美国社会学家泰德·H·尼尔森(Theodor Holm Nelson)在 1967 年于《Brief Words on the Hypertext》一文里提出的,

HypertextBy now the word “hypertext” has become generally accepted for branching and responding text, but the corresponding word “hypermedia”, meaning complexes of branching and responding graphics, movies and sound – as well as text – is much less used. Instead they use the strange term “interactive multimedia”: this is four syllables longer, and does not express the idea of extending hypertext.—— Theodor Holm Nelson Literary Machines, 1992

超文本(或超媒体)”指的是一种“能够对操作进行判断和响应的文本(或声音、图像等)”。

资源(Resource)

比如你正在阅读的一篇文章的内容本身(可以将其视作是某种信息、数据),我们称之为“资源”。无论你是在网上看的网页,还是打印出来看的文字稿,或者是在电脑屏幕上阅读、手机上浏览,尽管它呈现出来的样子都不一样,但其中的信息是不变的,你阅读的仍是同一个“资源”。

表征(Representation)

当你通过浏览器阅读这篇文章时,浏览器会向服务端发出请求“我需要这个资源的 HTML 格式”,那么服务端返回的这个 HTML,就被称之为“表征”,你通过其他方式拿到了文章的 PDF、Markdown、RSS 等其他形式的版本,它们也同样是一个资源的多种表征。可见,“表征”这个概念是指信息与用户交互时的表示形式,这跟应用分层中我们常说的“表示层”(Presentation Layer)的语义其实是一致的。

状态(State)

当你读完了这篇文章,想再接着看下一篇,你向服务器发出请求“给我下一篇文章”。但是“下一篇”是个相对概念,必须依赖“当前你正在阅读的文章是哪一篇”,这样服务器才能正确回应,那么这类在特定语境中才能产生的上下文信息就被称为“状态”。这里我们要注意,有状态(Stateful)还是无状态(Stateless) 都是相对于服务端来说的,服务器要完成“取下一篇”的请求,要么是自己记住用户的状态(这个用户现在阅读的是哪一篇文章,这是有状态),要么是客户端来记住状态,在请求的时候明确告诉服务器(我正在阅读某某文章,现在要读下一篇,这是无状态)。

转移(Transfer)

无论状态是由服务端还是客户端来提供的,“取下一篇”这个行为逻辑只能由服务端来提供。服务器通过某种方式,把“用户当前阅读的文章”转变成“下一篇文章”,这就被称为“表征状态转移”。

学习REST还需要理解的几个概念名词:

  1. 统一接口(Uniform Interface)
    “服务器通过某种方式”,让表征状态发生转移,具体指的是什么方式呢?这里指的就是HTTP 协议中已经提前约定好了一套“统一接口”,它包括:GET、HEAD、POST、PUT、DELETE、TRACE、OPTIONS 七种基本操作,任何一个支持 HTTP 协议的服务器都会遵守这套规定,对特定的 URI 采取这些操作,服务器就会触发相应的表征状态转移。
  2. 超文本驱动(Hypertext Driven)
    浏览器作为所有网站的通用的客户端,任何网站的导航(状态转移)行为都不可能是预置于浏览器代码之中,而是由服务器发出的请求响应信息(超文本)来驱动的。这点与其他带有客户端的软件有十分本质的区别,在那些软件中,业务逻辑往往是预置于程序代码之中的,有专门的页面控制器(无论在服务端还是在客户端中)来驱动页面的状态转移。
  3. 自描述消息(Self-Descriptive Messages)
    资源的表征可能存在多种形态,因此在传输给浏览器的消息中应当有明确的信息,来告知客户端该消息的类型以及该如何处理这条消息。一种被广泛采用的自描述方法,是在名为“Content-Type”的 HTTP Header 中标识出互联网媒体类型(MIME type),比如“Content-Type : application/json; charset=utf-8”,就说明了该资源会以 JSON 的格式返回,请使用 UTF-8 字符集进行处理。

RESTful 风格的系统特征

1服务端与客户端分离(Client-Server)

分离开用户界面和数据存储所关注的逻辑,有助于提高用户界面跨平台的可移植性。

2无状态(Stateless)

这是 REST 的一条关键原则,REST 希望服务器能不负责维护状态,每一次从客户端发送的请求中,应该包括所有必要的上下文信息,会话信息也由客户端保存维护,服务器端依据客户端传递的状态信息来进行业务处理,并且驱动整个应用的状态变迁。

至于客户端承担状态维护职责后的认证、授权等各方面的可信问题,都会有针对性的解决方案。

目前大多数的系统是达不到这个要求的,在服务端的内存、会话、数据库或者缓存等地方,持有一定的状态是一种现实情况,而且会是长期存在、被广泛使用的主流方案。

3可缓存(Cacheability)

前面我们提到的无状态服务,虽然提升了系统的可见性、可靠性和可伸缩性,但也降低了系统的网络性。通俗讲,某个功能使用有状态的架构只需要一次请求就能完成,而无状态的服务则可能会需要多个请求,或者在请求中带有冗余的信息。

为了缓解这个矛盾,REST 希望软件系统能够像万维网一样,客户端和中间的通讯传递者(代理)可以将部分服务端的应答缓存起来。

运作良好的缓存机制可以减少客户端、服务器之间的交互,甚至有些场景中可以完全避免交互,这就进一步提高了性能。

4分层系统(Layered System)

这里所指的并不是表示层、服务层、持久层这种意义上的分层,而是指客户端一般不需要知道是否直接连接到了最终的服务器,或者是连接到路径上的中间服务器。中间服务器可以通过负载均衡和共享缓存的机制,提高系统的可扩展性,这样也便于缓存、伸缩和安全策略的部署。

5统一接口(Uniform Interface)

REST 希望开发者面向资源编程,希望软件系统设计的重点放在抽象系统该有哪些资源上,而不是抽象系统该有哪些行为(服务)上。

统一接口也是 REST 最容易陷入争论的地方,基于网络的软件系统,到底是面向资源更好,还是面向服务更合适,这件事情在很长的时间里恐怕都不会有个定论。但是,有一个已经基本清晰的结论是:面向资源编程的抽象程度通常更高。

6按需代码(Code-On-Demand)

任何按照客户端(如浏览器)的请求,将可执行的软件程序从服务器发送到客户端的技术。它赋予了客户端无需事先知道,所有来自服务端的信息应该如何处理、如何运行的宽容度。即具体执行逻辑的代码存放在了服务端,只有当客户端请求了某个服务之后,代码才会被传输并在客户端机器中运行,结束后通常也会随即在客户端中被销毁掉。( 如Java Applet,WebAssembly)

REST 与 RPC 在思想上的差异

最主要的,REST 的基本思想是面向资源来抽象问题,它与此前流行的面向过程的编程思想,在抽象主体上有本质的差别。

降低了服务接口的学习成本

统一接口是 REST 的重要标志,它把对资源的标准操作都映射到了标准的 HTTP 方法上去,不会有什么 Interface Description Language 之类的协议存在。

资源天然具有集合与层次结构

以资源为中心抽象的接口,由于资源是名词,天然就可以产生集合与层次结构。很容易在程序接口中构造出这些资源的集合关系与层次关系。

REST 绑定于 HTTP 协议

面向资源编程并不是必须构筑在 HTTP 之上,但对于 REST 来说,这是优点,也是缺点。

因为 HTTP 本来就是面向资源而设计的网络协议,纯粹只用 HTTP(而不是 SOAP over HTTP 那样在再构筑协议)带来的好处,是不需要再去考虑 RPC 中的 Wire Protocol 问题了,REST 可以复用 HTTP 协议中已经定义的语义和相关基础支持来解决。HTTP 协议已经有效运作了 30 年,与其相关的技术基础设施已是千锤百炼,无比成熟。而它的坏处自然就是,当你想去考虑那些 HTTP 不提供的特性时,就束手无策了。

适合的,才是最好的。

此文章为2月Day10学习笔记,内容来源于极客时间《周志明的软件架构课

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值