设为首页 加入收藏

TOP

We FALL ASleep At Night, We Do REST Right(一)
2019-09-17 18:19:26 】 浏览:46
Tags:FALL ASleep Night REST Right

Github 同步发表链接

前言

笔者在上一篇文章中提过,任何一种非“强制性”约束同时也没有“标杆”工具支持的开发风格或协议,最后都会在不同的程序员手中得到不同的诠释,微服务是如此,DDD 是如此,笔者把它称为技术思想上的“康威定律”。不出意外的,REST 同样难逃此劫。光是在学习和收集资料的过程中,笔者就已经见过不下十多篇此类理解,甚至于在 url 中使用短划线或下划线连接单词也是众口难调。

尽管这只是小事。

微软也发布过关于如何设计 REST API 的开发指南,但是不幸的是,REST 的创始人 Roy Fielding 认为微软的 REST API 规范与 REST 没有多大关系。

“即使是我最糟糕的 REST 描述也比微软的 API 指南提供的总结或参考要好很多。”

那什么才是正确的 REST 描述呢,或者说,REST 是什么。本文的创作动机便是希冀于解决这样一个问题。

本文假设读者已经具备基本的 REST 和 Web 知识,哪怕你们现在认为 HTTP API 就是 REST API 也可。

REST 起源

REST 英文全称为 Representational State Transfer,又名“表述性状态移交”,是由 Roy Fielding 在《架构风格与基于网络的软件架构设计》一文中提出的一种架构风格(Architectural Style)。而在这篇 REST 圣经问世之前,R.F 博士就已经参与了 HTTP 1.0 协议规范的开发工作(1996年),并且负责了 HTTP 1.1 协议规范的制定(1997年)。

一种架构风格由一组准确命名的,相互协作的架构约束组成。当我们在谈论 REST 本质的时候,我们谈论的其实是架构约束。

REST 用以指导基于网络的分布式超媒体系统的设计和实现,Web(即万维网)就是一种典型的分布式超媒体系统。可以确定的是,在制定 HTTP 协议的过程中,R.F 博士就已经以 REST 架构风格作为指导原则来完成相关工作。论文中提到了以下内容:

“在过去的6年中,我们使用 REST 架构风格来指导现代 Web 架构的设计和开发。这个工作是与我所创作的 HTTP 和 URI 两个互联网规范共同完成的,这两个规范定义了在 Web 上进行交互的所有组件所使用的通用接口。”

“自从1994年起,REST 架构风格就被用来指导现代 Web 架构的设计与开发。”

“开发 REST 的动机是为 Web 的运转方式创建一种架构模型,使之成为 Web 协议标准的指导框架。”

“REST 的第一版开发于1994年10月至1995年8月之间,起初,在我编写 HTTP/1.0 规范和最初的 HTTP/1.1 建议时,将它用来作为表达各种 Web 概念的一种方法……”

Web 架构规范主要包括 HTTP, URI 和 HTML 等。

所以我们也不难理解为什么 REST 与 Web 和 HTTP 能够结合得如此紧密。尽管直到2000年,这只“鸡”才在下完鸡蛋后,出现在了世人面前。

REST 演化

REST 约束

无论是否愿意承认,REST 一开始就是为 Web 而服务的,可以这么说的是,REST 是现代 Web 的架构风格,Web 也是 REST 最典型和最成功的案例。包括在 R.F 博士的论文中,他也是在解决现代 Web 需求(无法控制的可伸缩性和独立部署)的过程中而逐步推导出 REST。前文已经提到一种架构风格是由一组准确命名的,相互协作的架构约束组成。而所谓架构约束,便是这个推导过程中最重要的产物。甚至高于 REST 本身。

早先的 Web 与 REST 所描述的模型有着大量出入,然而正是在对应的 HTTP 和 URI 规范出炉后,才有了所谓“现代 Web”的说法。笔者更愿意把“现代 Web”的定义期限定为1996年后。

客户端 - 服务端

设计与实现上的关注点分离。

无状态

在客户端没有发起请求时,服务器并不知道它的存在。同样的,服务器无须维护当前请求之外的客户端状态,从而改善服务器的可伸缩性。Session 和 Cookie 都是“需要”被抛弃的。
如果有些应用状态重要到服务器需要去关心,那它应该成为一个资源。

缓存

对于客户端而言,使用缓存则是维护状态和提升性能的更好做法。

统一接口

使 REST 架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间具有一个统一的接口。实现与他们所提供的服务是解耦的,这促进了独立的可进化性。同时这也引申出了其他的约束:资源识别;通过表述来操作资源;自描述信息;超媒体作为应用状态引擎(即 HATEOAS)。下文会专门说明。

分层系统

“分层系统”约束在“客户 - 服务端”约束的基础上增加了代理组件和网关组件。尽管笔者认为代理和网关都不是重点,“分层系统”约束更注重的是“在客户端和服务端之间添加一个组件应该是一个透明操作”,组件只能“看到”与其交互的相邻层(是不是想到了迪米特法则),使用层级来封装服务,同时能够支持负载均衡和诸如安全性检查的功能。

按需代码

这是六大约束中唯一的可选约束。REST 允许客户端通过下载并执行脚本或其他形式的代码,对客户端的功能进行扩展,从而提高客户端的灵活性和性能。通俗点说,HTML 中的 <script> 标签就是一种按需代码,尽管它可能会导致一些例如跨站脚本攻击这样的问题。

统一接口约束

R.F 博士在论文中针对六大约束中的“统一接口”做了额外的约束分解和说明,但遗憾的是并没有以列表的方式展示出来。但在接下来的内容中你可能就会发现,这几项可能是目前大部分开发者践行 REST 原则时所遵循的全部标准。

资源识别

REST 对于信息的核心抽象是资源,任何能够被命名的信息都可以称为是资源,只要你的想象力允许。资源一词通常和“可寻址性”绑定,一个或多个 URI 标识一个资源。如果资源的 URI 发生了变化,服务器应该使用超媒体引导客户端访问新的 URI 或提示对应信息。

通过表述来操作资源

当客户端对一个资源发起一个请求时,服务器会以一种有效的方式提供一个采集了资源信息的文档作为回应。这就是表述——一种以机器可读的方式对资源当前状态的说明。客户端和服务器之间也可以继续传递表述,从而对资源执行某种操作。客户端从来不会直接看到资源,能看到的都是资源的表述。可以这么说的是,服务器发送的表述用于描述资源当前的状态,客户端发送的表述用于描述客户端希望资源拥有的状态,这就是表述性状态转移/移交。

一个表述由一个“字节序列”和描述这些字节的“表述元数据”构成,且不与服务器端代码绑定,这意味着当服务器端的资源实现和业务操作代码发生变化时,可以选择不更改资源的呈现方式。

值得注意的是,一般人通常会将表述认为成资源的“值”,这虽然可以理解,但是当你请求一个天气服务时,千万不要认为表述一定便是温度等确定的值信息,因为它仍然可能是某次响应中的错误提示。一个表述的具体含义取决于消息中的控制数据。

“控制数据定义了在组件之间移交的消息的用途,例如被请求的动作或相应的含义。它也可用于提供请求的参数,或覆盖某些连接元素的默认行为。例如,可以使用(包含在请求或响应消息中的)控制数据来修改缓存的行为

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Spring Cloud简介 下一篇大数据小视角3:CarbonData,来自..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目