Java技术升华架构设计微服务

REST架构详解

2019-05-21  本文已影响151人  寒江雪_独钓

1.前言

在「远古时代」前端后端是融合在一起的,比如之前的PHP,JSP,ASP等等。近年来随着移动互联网的飞速发展,各种类型的Client端层出不穷,就需要通过一套统一的接口分别为Web,iOS和Android乃至桌面端提供服务。另外对于广大平台来说,比如Facebook platform,微博开放平台,微信、QQ公共平台等,它们不需要有显式的前端,只需要一套提供服务的接口,于是RESTful更是它们最好的选择。

2.RESTful是什么

越来越多的人开始意识到,网站即软件,而且是一种新型的软件。

这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时、高并发等特点。

网站开发,完全可以采用软件开发的模式。但是传统上,软件和网络是两个不同的领域,很少有交集;软件开发主要针对单机环境,网络则主要研究系统之间的通信。互联网的兴起,使得这两个领域开始融合,现在我们必须考虑,如何开发在互联网环境中使用的软件。

RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

需要注意的是,REST是一种设计风格而不是标准,如果一个架构符合REST原则,我们就称它为RESTful架构。

2.1、起源

在互联网行业,实践总是走在理论的前面。Web 发展到了 1995 年,在 CGI、ASP 等技术出现之后,沿用了多年、主要面向静态文档的 HTTP/1.0 协议已经无法满足 Web 应用的开发需求,因此需要设计新版本的 HTTP 协议。在 HTTP/1.0 协议专家组之中,有一位年轻人脱颖而出,显示出了不凡的洞察力,后来他成为了 HTTP/1.1 协议专家组的负责人。这位年轻人就是 Apache HTTP 服务器的核心开发者 Roy Fielding,他还是 Apache 软件基金会的合作创始人。

Roy Fielding 和他的同事们在 HTTP/1.1 协议的设计工作中,对于 Web 之所以取得巨大成功,在技术架构方面的因素做了一番深入的总结。Fielding 将这些总结纳入到了一套理论框架之中,然后使用这套理论框架中的指导原则,来指导 HTTP/1.1 协议的设计方向。HTTP/1.1 协议的第一个草稿是在 1996 年 1 月发布的,经过了三年多时间的修订,于 1999 年 6 月成为了 IETF 的正式规范(包括了 RFC 2616 以及用于对客户端做身份认证的 RFC 2617)。HTTP/1.1 协议设计的极为成功,以至于发布之后整整 10 年时间里,都没有多少人认为有修订的必要。用来指导 HTTP/1.1 协议设计的这套理论框架,最初是以备忘录的形式在专家组成员之间交流,除了 IETF/W3C 的专家圈子,并没有在外界广泛流传。Fielding 在完成 HTTP/1.1 协议的设计工作之后,回到了加州大学欧文分校继续攻读自己的博士学位。

第二年(2000 年)在他的博士学位论文 Architectural Styles and the Design of Network-based Software Architectures 中,Fielding 更为系统、严谨地阐述了这套理论框架,并且使用这套理论框架推导出了一种新的架构风格,并且为这种架构风格取了一个费解难懂名字“REST”,即Representational State Transfer(表现层状态转化,一般是这个翻译,但你听听这是人话吗?)的缩写.应该是缺少了主语。全称是 Resource Representational State Transfer:通俗来讲就是:资源在网络中以某种表现形式进行状态转移。分解开来:

Resource: 资源,即数据

Representional:某种表现形式,比如xml,json.

State Transfer:状态变化。通过HTTP动词实现。

2.2、REST架构的标志

根据理查德森模型,REST架构的成熟度有3分等级

gloryofrest.png

当然另外一种更简便的总结式可以这样理解:

RESTful简单来说就是:URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。

2.3、超媒体(hypermedia)

根据Roy的严格规定,超媒体(hypermedia)是REST的先决条件,任何其他东西都不应该自我标榜为REST,这里要要先解释一个概念:超媒体,wiki上面有这样一个解释:

多媒体(Multimedia),在电脑应用系统中,组合两种或两种以上媒体的一种人机交互式资讯交流和传播媒体。使用的媒体包括文字、图片、照片、声音(包含音乐、语音旁白、特殊音效)、动画和影片,以及程序所提供的互动功能。

超媒体(Hypermedia)是多媒体系统中的一个子集,超媒体系统是使用超链接(Hyperlink)构成的全球资讯系统,全球资讯系统是互联网上使用TCP/IP协议和UDP/IP协议的应用系统。2D的多媒体网页使用HTML、XML等语言编写,3d的多媒体网页使用VRML等语言编写。目前许多多媒体作品使用光碟发行,以后将更多地使用网络发行。

此种关键的角色还是超链接,使用超媒体作为应用引擎状态,意思是应用引擎状态变更,由客户端访问不同的超媒体资源驱动。

如下示例:

GET :https://api.github.com/authorizations
{
  "author": "github",
  "video": {
    "large": "https://api.github.com/Japan/large.avi.png",
    "medium": "https://api.github.com/Japan/media.avi.png",
    "small": "https://api.github.com/Japan/small.avi.png"
  }
}

由于在响应中包含了链接地址,因此使用该API的客户端就能够自由选择要下载怎样的信息。这些链接告知了客户端有哪些选择,并且它们的地址在哪里。

因此在这里我们无需同时返回三个不同版本小视频,我们所做的只是告诉客户端有三种不同清晰度可以选择,并且告诉客户端能够在哪里找到这些avi。

这样一来,客户端就能够根据不同的场景,做出符合自身需要的选择。而且,如果客户端只需要一种高清无码格式的,那就无需下载全部三种。这样一来可谓一箭三雕:既减少了网络负载,又增进了客户端的灵活性,更增进了API的可探索性。

超媒体的核心概念就是所谓的元素,而这些相互链接的资源实际上描述了一个协议,即引导我们达成某个目标的一系列步骤:

例如订购一杯咖啡所需要的点单、付款、取咖啡等等。这就是超媒体的本质:经由资源之间的链接,我们改变整个应用的状态,即超媒体转换了,分布式应用的状态。需要注意的是,服务器和消费者两者间,交换的是资源状态的表述,而不是应用的状态,被转移的表述中,包括了反应,应用状态的链接。

2.4、REST误解

现在看来,REST在2000年那个时代,确实是超前于时代的。Web开发者社区对于HTTP的设计意图存在着大量的误解,由此导致了对于HTTP的大量低效率的误用。这个情况持续一直到2005年Web 2.0的崛起。那个时候,DCOM、EJB、SOAP/WSDL这些DO风格的架构由于难以满足互联网环境对分布式应用架构设计的约束,与Web自身的架构风格REST相冲突,很难融入到Web之中。所谓的「Web Services」,其实除了将HTTP作为底层的传输协议外,跟(互联网环境中的)真正的Web没有什么关系。

而随着Ruby on Rails这个著名的Web开发框架开始大力支持REST开发之后,一线的Web开发者才真正接触到了REST。然而Rails所支持的REST开发将对资源的操作局限于CRUD(创建、获取、修改、删除)的语义(即,将对资源的CRUD操作映射到 GET/POST/PUT/DELETE四个HTTP方法),这其实是收窄了REST的适用范围。其他编程语言的Web开发框架(例如Java语言的 Struts、Spring MVC等等)也紧接着模仿了Rails的方式开始支持REST开发,然而这更加导致了一线的Web开发者误以为:REST开发就是 通过GET/POST/PUT/DELETE四个HTTP方法对资源执行CRUD操作。甚至还有很多仅仅使用了HTTP,而没有使用SOAP的Web服 务API,都自称是REST风格(RESTful)的API。

对于什么才是真正的REST风格的误解是如此之多,而将REST作为一个便于营销的 buzzword的挂羊头卖狗肉者也是如此之多,以至于REST的创造者Fielding终于忍无可忍了。2008年10月Fielding写了一篇博 客,做出了一个非常明确的断言:REST APIs must be hypertext-driven!(REST API必须是超文本驱动的!)超文本驱动这个理念变成了一个缩写词HATEOAS,这个缩写词来自于当初Fielding博士论文中的一句话: hypermedia as the engine of application state(将超媒体作为应用状态的引擎)。

其实超文本驱动(Hypertext Driven)的理念才是REST架构风格最核心的理念,也是REST风格的架构达到松耦合目标的根本原因。

3.REST 架构风格的推导过程

3.1 REST 所继承的架构风格约束(图 1)
restconstrain.png

在图 1 中,每一个椭圆形里面的缩写词代表了一种架构风格,而每一个箭头边的单词代表了一种架构约束。

3.2. 在论文中推导出的 REST 架构风格如下图所示:
deduce.png
3.3 .一个基于 REST 的架构的过程视图

而 HTTP/1.1 协议作为一种 REST 架构风格的架构实例,其架构如下图所示:

httprestful.png

用户代理处在三个并行交互(a、b 和 c)的中间。用户代理的客户端连接器缓存无法满足请求,因此它根据每个资源标识符的属性和客户端连接器的配置,将每个请求路由到资源的来源。

请求(a)被发送到一个本地代理,代理随后访问一个通过 DNS 查找发现的缓存网关,该网关将这个请求转发到一个能够满足该请求的来源服务器,服务器的内部资源由一个封装过的对象请求代理(object request broker)架构来定义。

请求(b)直接发送到一个来源服务器,它能够通过自己的缓存来满足这个请求。

请求(c)被发送到一个代理,它能够直接访问 WAIS(一种与 Web 架构分离的信息服务),并将 WAIS 的响应翻译为一种通用的连接器接口能够识别的格式。每一个组件只知道与它们自己的客户端或服务器连接器的交互;

4. 为什么要用RESTful结构呢?

4.1. 从架构风格的抽象角度来看,常见的分布式应用架构风格有三种:

DO 和 RPC 这两种架构风格在企业应用中非常普遍,而 REST 则是 Web 应用的架构风格,它们之间有非常大的差别。

4.2. REST和DO的差别在于:
4.3. REST与RPC的差别在于:
4.4. REST 架构风格优越之处:

比较了三种架构风格之间的差别之后,从面向实用的角度来看,REST 架构风格可以为 Web 开发者带来三方面的利益:

采用REST架构风格,对于开发、测试、运维人员来说都会更简单。可以充分利用大量HTTP服务端和客户端开发库、Web功能测试/性能测试工具、HTTP缓存、HTTP代理服务器、防火墙。这些开发库和基础设施早已成为日常用品,不需要什么高科技(例如神奇昂贵的应用服务器、中间件)就能解决大多数可伸缩性方面的问题。

充分利用好通讯链各个位置的HTTP缓存组件,可以带来更好的伸缩性。其实很多时候,在Web前端做性能优化,产生的效果不亚于仅仅在服务器端做性能优化,但是HTTP协议层面的缓存常常被一些看似很牛逼的人给忽略掉了。

统一接口 + 超媒体引擎驱动,带来了最大限度的松耦合。允许服务器和客户端在很大范围内,相对独立的运行。对于设计面向企业内网的API来说,松耦合并不是一个很重要的设计关注点。但是对于设计面向互联网的API来说,松耦合成了一个必选项,不仅仅在设计时应该关注,而且应该昂在最优的位子。

下面这段话出自知乎覃超,是一个浅显易懂的总结:

大家都知道"古代"网页都是前端后端融在一起的,比如之前的PHP,JSP等。在之前的桌面时代问题不大,但是近年来移动互联网的发展,各种类型的Client层出不穷,RESTful可以通过一套统一的接口为 Web,iOS和Android提供服务。另外对于广大平台来说,比如Facebook platform,微博开放平台,微信公共平台等,它们不需要有显式的前端,只需要一套提供服务的接口,于是RESTful更是它们最好的选择。在RESTful架构下:


restful.jpg

5. RESTful如何设计

服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词),查看全部状态码定义点击这里

* 200 OK-[GET]:服务器成功返回请求数据,该操作是幂等的。
* 201 create -[POST/PUT/PATCH]:用户新建或者修改数据
* 202 Accept - [*]标识一个请求进入后台排队(异步任务)
* 204 no content - [DELETE]:用户删除数据成功
* 400 invalid requests- [POST/PUT/PATCH]:用户发出的请求错误,服务器没有进行新建或者修改的操作,该操作是幂等的。
* 401 Unauthorized- [*]:标识没有权限(令牌,用户名,密码错误)。
* 403 Forbidden - [*]: 标识用户得到授权(与401错误相对),但是访问是被禁止的。
* 404 not found - [*]: y用户发出的请求针对的是不是存在的记录,服务器没进行操作,这个操作是幂等的。
* 406 Not Acceptable - [GET]:用户请求格式不可得:(比如用户请求的是json格式,但是只要xml格式)
* 410 Gone - [GET]:用户请求资源被永久删除,且不会再得到。
* 422 Unprocesable entity - [POST/PUT/PATCH]当创建一个对象时候,发生一个验证错误。
* 500 internal server error - [*] :服务器发生错误,用户将无法判断发出的请求是否成功。

另外附上GitHub的API设计,更具参考价值。

6. 各端的具体实现

如上图说是,service统一提供了一套RESTful API, web+android+ios作为同级调用API,现在都有一些比较成熟的框架来帮助开发者。

1. Server

2. Android

3. iOS

4. Web

7. Django REST Framework使用

Django REST Framework应用会在下一遍文章中做详细分析。

参考资料链接:

REST APIs must be hypertext-driven

REST 架构该怎么生动地理解?

理解RESTful架构

RESTful API 设计指南

Richardson Maturity Model

Status Code Definitions

理解本真的 REST 架构风格

架构风格与基于网络的软件架构设计(Roy Fielding 博士论文中文版)

上一篇下一篇

猜你喜欢

热点阅读