理解RESTful
纠葛的问题:REST和RPC的对比?
思想上,概念上,使用范围 RPC和REST都完全不一样,本质上并不是同一类东西,只有部分功能重合。REST和RPC在思想上存在差异的核心是:抽象目标不一样,也就是面向资源的编程思想和面向过程的编程思想之间的差异。
REST:本质上不是一种协议,而是一种风格。
理解REST
REST 概念的提出来自于罗伊·菲尔丁(Roy Fielding)在 2000 年发表的博士论文:《Architectural Styles and the Design of Network-based Sorftware Architectures》。
REST全称为:Representational State Transfer 即表征状态转移。
为何常常使用HTTP搭配REST
REST实际上是HTT(Hyper Text Transfer,超文本传输)的进一步抽象,就想是接口和实现类之间的关系。(即REST是接口,HTT是实现)。
Representation 表征 (对Resource的转换):
浏览器向客户端请求资源的HTML格式,那么返回的这个HTML我们就可以称之为:表征。也可以理解为MVC模式中的:表示层。
State 状态:
特定语境中产生的上下文信息称之为“状态”。注意Stateful 和 Stateless是针对的服务端没有记录上下文。浏览器每次携带上下文来请求服务端,比如:JWT技术
Transfer 转移:
服务端通过浏览器提供的信息,由当前的表示层转移到新的标识层,这就被成为:表征状态转移。
如何评价一个系统是否符合RESTful ?
Fielding 认为,一套理想的、完全满足 REST 的系统应该满足以下六个特征。
服务端与客户端分离(Client-Server)
无状态(Stateless)
REST希望服务器不能负责维护状态,每一次从客户端发送的请求中,应该包括所有必要的上下文信息,会话信息也由客户端保存维护。服务器端依据客户端传递的状态信息来进行业务处理,并且驱动整个应用的状态变迁。提升了系统的可见性、可靠性和可伸缩性(大多数系统达不到这个要求,越复杂,越大型的系统越是如此。)
可缓存(Cacheability)
REST希望客户端和中间的通讯传递者(代理)可以将部分服务端应答缓存起来。通过良好的缓存机制,减少客户端和服务端的交互。
分层系统(Layered System)
不是传统的MVC这样的分层。而是指客户端一般不需要知道是否直接链接到了最终的服务器,或者是链接到了路径上的中间服务器。中间服务器可以通过负载均衡和共享缓存机制,提高系统的可扩展性。这样也便于缓存,伸缩和安全策略的部署。
统一接口(Uniform Interface)
REST希望开发者面向资源编程,希望软件系统设计重点放放在抽象系统有哪些资源上,而不是抽象系统该有哪些行为上。
举例:
几乎每个系统都会有登录和注销功能,如果你登录对应的是login() 注销对应于loginout()。那么如果面向资源可以理解成为:登录是PUT session 注销是DELETE session,这样你只需要设计一种“session”资源即可。查询登录用户使用GET session。
Felding给出三个建议:
- 系统要做到每次请求中都包含资源的ID,所有操作都通过ID完成。
- 每个资源都应该有自描述信息。
- 通过超文本来驱动应用状态的转移。
按需代码(Code-On-Demand)
RESTful带来的优点
降低了服务接口的学习成本
它把资源的标准操作都映射到了标准的HTTP方法上(GET,PUT,POST,DELETE)对每个资源的语义一致。无需额外定义。
资源天然具有集合与层次结构
1
GET /book/{bookId}/chapter/{chapterNumber}
天热的集合与层次关系。
RESTful绑定于HTTP协议
面向资源编程并不是必须构筑在 HTTP 之上。
但是HTTP 协议已经有效运作了 30 年,与其相关的技术基础设施已是千锤百炼,无比成熟。而它的坏处自然就是,当你想去考虑那些 HTTP 不提供的特性时,就束手无策了。
RESTful缺点
面向资源只适合做CRUD,只有面向过程,面向对象编程才能处理真正复杂的业务逻辑。
REST与HTTP完全绑定,不适用于要求高性能传输场景当中。
面向资源编程与协议无关,但是 REST(特指 Fielding 论文中所定义的 REST,而不是泛指面向资源的思想)的确依赖着 HTTP 协议的标准方法、状态码和协议头等各个方面。
REST 不利于事务支持。
REST 没有传输可靠性支持。
应对传输可靠性最简单粗暴的做法,就是把消息再重发一遍。这种简单处理能够成立的前提,是服务具有幂等性(Idempotency),也就是说服务被重复执行多次的效果与执行一次是相等的。
REST 缺乏对资源进行“部分”和“批量”的处理能力。
就是缺少对资源的“部分”操作的支持。要解决批量操作这类问题,目前一种从理论上看还比较优秀的解决方案是GraphQL(但实际使用人数并不多)。GraphQL 是由 Facebook 提出并开源的一种面向资源 API 的数据查询语言。它和 SQL 一样,挂了个“查询语言”的名字,但其实 CRUD 都能做。
参考链接
周志明的软件架构课:https://time.geekbang.org/column/article/317164
李锟谈 Fielding 博士 REST 论文中文版发布:https://www.infoq.cn/article/2007/07/dlee-fielding-rest/
Fielding论文:https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
REST和RPC对比结论:
无论是思想上,概念上,还是使用范围上,REST和RPC都不完全一样,本质上并不是同一个类型的东西。充其量是相似,在应用中会存在重合功能。
- 思想上差异:抽象目标不一样,REST是面向资源的编程思想,RPC是面向过程。
- 概念上:REST并不是一种远程服务调用协议,也可以说它就不是一种协议,只是一种风格。RPC是作为一种远程调用协议的存在。
- 试用范围:REST和RPC作为主流的两种远程调用方式,在使用上确实有重合之处。