使用REST风格架构您需要知道的一些事
1. REST的由来
REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。
上世纪90年代面对高速发展的互联网规模,HTTP1.0需要进一步改进。Roy Fielding 着手制定HTTP1.1的标准及后续扩展工作。HTTP1.1重视降低WEB系统开发的复杂性(通过增强HTTP的请求头和响应头),提高系统的可扩展性(通过更容易的缓存指令)以及其他性能优化工作(比如长连接和多个请求和响应可以重叠等)。
Roy Fielding在制定HTTP时有一个愿景:Web世界的应用程序应随着不断的超连接跳转来实现应用系统状态迁移,所以HTTP应该是一个应用协议,而不是一个纯粹的超文本传输协议。
这就是REST的由来。当我们在谈论REST的时候,表示我们在谈论Web世界的应用一种基于HTTP的架构风格。
2. REST的构成

2.1. 资源
在restful中资源是核心抽象,任何会被互联网组件访问的信息都是资源,并用一个URL/URN来标识。
举例来说,获取某网站的2017年10月1号的天气信息,该网站可以命名改信息为http://www.somesite.com/weather/2017/10/1或者
http://www.somesite.com/weather?year=2017&month=10&day=1。客户端浏览器能用GET方法合法的获取该资源。
如果天气采集人员要创建2017年10月1号的天气信息,则用POST方法提交表单给http://www.somesite.com/weather完成创建资源工作。
http://www.somesite.com/weather并没有制定哪一天的天气信息,但它确实资源,这体现资源的抽象性。

2.2. 资源的表述
资源的表述是指资源的表现形式,这些形式由请求方和资源提供方通过HTTP协商指定。包括以下内容:
2.2.1. MIME(Multipurpose Internet Mail Extensions)
MIME是多用途互联网邮件扩展类型,它是一个互联网标准,扩展了电子邮件标准,使其能够支持:
非ASCII字符文本;非文本格式附件(二进制、声音、图像等);由多部分(multiple parts)组成的消息体;包含非ASCII字符的头信息(Header information)。
比如下图,客户端表示能接受json(首选),text(次选)以及任意格式(再次选);服务器端返回json内容给客户端:

2.2.2. 缓存约定
所以的资源操作包括读取和更新操作,对于不频繁更新的数据数据多数可以进行缓存。这种换成越靠近客户端,用户体验越好,即提高了整体系统的可用性。
HTTP采取多层缓存机制,系统可以定义自己的缓存策略。(此处是否需要讲公共缓存,私有缓存,运行机制?)

其中代理服务器和缓存服务器应该只对公共缓存表述进行缓存,浏览器缓存对公共和私有的缓存表述都能进行缓存。通常代理服务器的缓存行为是用户所属组织支持的,不属于应用系统的行为。
2.3. 资源的自描述
资源的自描述是指:资源的表述里面应该包括资源当前状态的描述,以及对该资源或相关资源进一步操作的超链接。
2.3.1. 资源的当前状态
资源的当前状态由以下几项共同组成:
- 属于该资源的信息项目的值,比如订单的编号,创建日期。
- 相关资源的链接,比如订单的客户链接以及订单明细链接。
- 表示资源将来会迁移到某种可能状态的链接,比如迁移到完成状态的链接:/order/1/completeness POST
- 对应该资源与其他资源相关联的任何业务规则的求值结果,比如订单统计表:/order/statistics/year/2017 GET
下图是一个订单状态的json表述:

2.3.2. 操作资源的统一接口
HTTP的初衷是应用层协议,HTTP是REST风格的。HTTP的动作提供了操作字体的统一接口。
| 动作 | 接口作用 | 重复操作效果 |
|---|---|---|
| POST | 创建资源 | 不幂等 |
| PUT | 整体更新资源 | 幂等 |
| PATCH | 部分更新资源 | 不幂等 |
| DELETE | 删除资源 | 幂等 |
| GET | 获取资源 | 幂等 |
幂等 表示动作的重复执行不会再产生副作用(引起资源状态变化),比如删除一个资源后再次删除也不会产生作用,同时系统也不应该返回错误信息,而是总是返回成功。
RPC或者SOAP风格的架构下HTTP是作为传输协议使用。
2.3.3. 请求的无状态
REST的无状态是指客户端请求服务器时,应提供足够的信息以让服务器能理解并提供服务。无状态的好处包括:
- 改善可见性(监视系统不必为了确定一个请求的全部性质而去查看请求之外的其他请求)
- 改善可靠性(减轻了从局部故障中恢复的任务量)
- 改善可伸缩性(服务端不必在多个请求直接保存状态,从而允许服务器迅速释放资源)
缺点:
- 由于服务器不能保持会话状态数据,则会造成在每一次请求中发送大量重复的数据,可能会降低网络性能。
下图是请求有状态和无状态的对比例子:

2.4. HATEOAS
HATEOAS(The Hypermedia As The Engine Of Application Statue),中文意思是“将超媒体作为应用状态的引擎”,这是REST的最高目标(也叫主要架构约束)。
HATEOAS包括两个概念:
- 应用状态由应用(系统)中的各资源状态组成,资源状态的变化导致应用状态的变化。
- 通过在资源表述中添加状态迁移的超链接引导客户端改变资源状态。
比如:销售订单在创建后,客户端通过GET操作获取一个订单信息,然后请求“审批订单”链接使订单变成“已审批“状态。客户端再请求”执行订单“完成订单。这就是一个简单工作流程。

3. REST与分布式事物
分布式系统中事物是一个重要话题,遗憾的是REST作为一种系统风格,并没有约定对事物管理进行规定。事物是服务器端的事情,不论采用何种事物处理方式都要避免对客户使用rest服务的影响。
4. REST的典型应用案例
1. GitHub Developer API
比如API:列出pull的评论
GET /repos/:owner/:repo/pulls/:number/reviews

官网: https://developer.github.com/v3/pulls/reviews/
2. LinkIn 开发者中心
比如API:获取当前用户的信息
GET /v1/people/~?

官网:https://developer.linkedin.com/zh-cn/docs/rest-api
5. REST vs RPC
REST式的Web服务和RPC式的Web服务在接口定义上的区别是,REST使用HTTP通用方法作为统一接口的标准词汇,REST式的Web服务所提供的方法信息都在HTTP方法里,而RPC式的web服务所提供的方法信息在SOAP/HTTP信封里(其封装的格式通常是HTTP或者是SOAP),每个RPC式的web服务都会公布一套符合自己商业逻辑的方法词汇。
RPC的典型案例
1. 百度lbs服务API
比如API: 行政区划区域检索,之所以是rpc,是由于:
- 在参数中指定了资源格式MIME(此例是json),就是说资源表述由百度官方自定义协议解释。
- 返回状态和错误信息封装在返回结果中,说明对于错误处理也由百度官方自定义协议解释。
- 返回结果关心的是满足当前接口数据,如果想进一步了解街道信息,客户端须根据获取街道信息API定义获取。
http://api.map.baidu.com/place/v2/search?query=ATM机&tag=银行®ion=北京&output=json&ak=您的ak GET

如果经过rest风格改造,行政区划区域检索API的返回结果可以是如下形式:

注:百度lbs不是面向应用状态迁移设计,因此采用rpc也是合适的。
2.Saleforce SOAP API
Saleforce提供了SOAP(简单对象访问协议) API,SOAP 通过发布WSDL(网络服务描述语言)文件来描述服务器提供的API的输入参数结构和返回数据结构以及可能的异常信息。客户端通过WSDL生成客户端调用代码(SOAP语言无关,可跨开发语言调用),就能调用远程的服务API。
下图表示表示了Saleforce的提供的API的WSDL:

注:Saleforce也提供了REST的API。
以下是二者的主要区别:
| REST | RPC | |
|---|---|---|
| HTTP协议地位 | 应用协议 | 传输协议或者不用 |
| 传输协议 | HTTP | HTTP或者TCP |
| 消息序列化类型 | MIME | MIME或者自定义协议 |
| 传输性能 | 中 | 高 |
| 服务处理性能 | 中 | 高 |
| 接口特点 | 通用(HTTP动作) | 自定义接口动作 |
| 应用协议 | HTTP | 自定义 |
| 应用状态迁移方式 | 资源状态变化 | 业务数据状态变化 |
| 缓存扩展性 | 强 | 自定义 |
| 客户端耦合力度(协议) | 弱 | 强 |
| 客户端代码执行 | 按需提供(JS,CSS,HTML等) | 默认不支持 |
| 客户端的库支持 | 不需要 | 最好有,且和服务同步升级 |
| 防火墙穿透力 | 强 | 默认不支持 |
| 公网组件支持度 | 现成支持,包括(反向)代理服务器,防火墙,缓存服务器,用户代理(浏览器等) | 需自行支持(http传输除外) |
| 企业应用标准化程度 | 低(企业自定义) | 中(基于SOAP协议,各厂商产品容易集成) |
以下是主流RPC和REST框架
| 框架 | 特点 | 开发语言 |
|---|---|---|
| Thrift | Thrift是一个跨语言的RPC框架,自带的代码生成引擎大幅提高了开发效率,从而使它如此流行。 最初由Facebook团队设计开发,现在已贡献给Apache |
多语言 |
| Dubbo | Dubbo是阿里巴巴开源的专门为Java设计的、成熟的RPC框架。支持基本的服务治理,所有服务治理 功能均在Client端集成:服务发现、负载均衡、容错、监控等 |
Java |
| Spring HATEOAS | Spring HATEOAS 可以很方便创建 基于HATEOAS 原则的REST 风格接口 , 但需要依赖于 Spring 和 Spring MVC |
Java |
6. 总结
HTTP的本意是方便应用系统实现REST的架构,不过人们在早期并没有意识到它的优点,因此目前更多使用的是RPC框架,因为REST 对开发人员的能力要求更高。综上,REST具有以下主要特点:
- 以HTTP为应用协议。
- 基于WEB中间件进行扩展:缓存代理提高缓存扩展,反向代理提供负载均衡和内外网协议转化(HTTPS和HTTP之间)。
- 请求的无状态:由于服务器没有会话上下文信息,提高系统的可伸缩性。缺点是传输冗余一些。
- 多级缓存:客户端代理,代理服务器,缓存服务器提供了强大缓存能力,提高了系统的可用性。
- 对资源内容的描述方式,比如MIME协商或者在此基础上的扩展格式,保证了系统的简单性和通用性。
- 资源状态变化促成应用状态迁移(HATEOAS),可使开发者以资源为中心建模,这种设计相对简单。
- 资源表述中链接广告了应用的状态流,但并不强迫客户端进行处理,有利于客户端平滑升级。
使用REST风格架构您需要知道的一些事的更多相关文章
- REST 风格架构
------------------------------ 时间不多了, 抓紧做一些有意义的事情 REST 风格架构 1. 他是面向资源进行开发的 2. 他是基于HTTP 协议进行开发 ...
- REST风格架构
一说到rest 大家都耳熟能详,很多人的第一反应就是其是前后端请求后台的一种通信方式,甚至有些人将REST 和RPC 混为一谈,认为两者都是基于HTTP类似的东西.实际上很少人能叙述REST 所提出的 ...
- 向架构师进军-->可重用架构资源
如果你对项目管理.系统架构有兴趣,请加微信订阅号"softjg",加入这个PM.架构师的大家庭 软件架构有三个主要来源:拿取.方法以及直觉.拿取也就是可重用资源.对于一个标准的系统 ...
- Rest风格WEB服务(Rest Style Web Service)的真相
http://blog.csdn.net/jia20003/article/details/8365585 Rest风格WEB服务(Rest Style Web Service)的真相 分类: J2E ...
- SpringMVC+Json构建基于Restful风格的应用(转)
一.spring 版本:spring-framework-3.2.7.RELEASE 二.所需其它Jar包: 三.主要代码: web.xml <?xml version="1.0&qu ...
- [我所理解的REST] 3.基于网络应用的架构
上篇中解释到什么是架构风格和应该以怎样的视角来理解REST(Web的架构风格).本篇来介绍一组自洽的术语,用它来描述和解释软件架构:以及列举下对于基于网络的应用来说,哪些点是需要我们重点关注的. 1 ...
- [解读REST] 3.基于网络应用的架构
链接上文[解读REST] 2.REST用来干什么的?,上文中解释到什么是架构风格和应该以怎样的视角来理解REST(Web的架构风格).本篇来介绍一组自洽的术语,用它来描述和解释软件架构:以及列举下对于 ...
- NLayerAppV3--.net Core2实现的DDD分层架构
虽然每天的工作都是CURD.还是使用着传统的三层架构.使用着.net Framework,但是这并不能影响我学习DDD和.net core. 总是希望软件在应对复杂多变的场景时能够游刃有余,在解决问题 ...
- asp.net core系列 64 结合eShopOnWeb全面认识领域模型架构
一.项目分析 在上篇中介绍了什么是"干净架构",DDD符合了这种干净架构的特点,重点描述了DDD架构遵循的依赖倒置原则,使软件达到了低藕合.eShopOnWeb项目是学习DDD领域 ...
随机推荐
- 上传图文{"errcode":40007,"errmsg":"invalid media_id"}解决方案
{"errcode":40007,"errmsg":"invalid media_id"}解决方案 网上关于这个问题的解决一般是把thumb ...
- python爬虫如何入门
学爬虫是循序渐进的过程,作为零基础小白,大体上可分为三个阶段,第一阶段是入门,掌握必备的基础知识,第二阶段是模仿,跟着别人的爬虫代码学,弄懂每一行代码,第三阶段是自己动手,这个阶段你开始有自己的解题思 ...
- HDU1005 Number Sequence (奇技淫巧模拟)
A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mo ...
- poj 2720 Last Digits
Last Digits Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2233 Accepted: 474 Descri ...
- js foreach、map函数
语法:forEach和map都支持2个参数:一个是回调函数(item,index,input)和上下文: •forEach:用来遍历数组中的每一项:这个方法执行是没有返回值的,对原来数组也没有影响: ...
- cocos2d导入iOS原生项目
最近公司最新发下任务让融合一个cocos2dx写的游戏项目融合进现有项目,当看到要求时内心瞬间无数羊驼奔腾.------ 虽说内心是拒绝的,但是任务已经派发就必须要完成啊.所以在网上搜了大量的融入教程 ...
- day3--深入学习命令总结
1.查看命令帮助的几种方法 a.[命令] --help 适用于一般命令,非内置命令 b.man [命令] 适用于一般命令,非内置命令 c.help [命令] 适用于内置命令 d ...
- 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)
实现功能 以上的代码我们发现.我们都是将@ComponentScan扫描的路径下的所有类都加载到容器中的. 而实际需求,我们并不希望所有的类都创建对象,而是加了组件注解@Controller,@Ser ...
- 初识React-Redux之粗暴理解入门
权当暂记 日后再行补充完善,若有阅读者,请翻到下文黄色标题'从这里开始'起阅读. Rudex在我看来最本质做的事情就是将所有的State属性统一存储(一个属性就是一个注册到store的Reducer) ...
- JavaScript 经典之一 闭包
作为一个前端开发者,闭包是必须要攻克掉的障碍.据说好多面试者挂在闭包面试上.下面我就给大家讲一下我理解中的闭包.不说太多的废话,直接进入主题. 变量作用域 学习编程语言需要明白,变量的作用域.变量作用 ...