[toc]
访问远程服务#
1 远程服务调用#
这一个章节主要讲解rpc的设计理念和发展历史。
先是讲解了IPC(进程间通信)所需要的各个必要因素
接着解释RPC 是IPC的一种特例(这是最初科学家们的想法)
但PRC存在很多可靠性的问题,并不能直接等同IPC的扩展。
接着提出了RPC的三个基本问题:
- 如何表示数据
即序列化协议, 有grpc的proto-buffer、json、xml、java-rmi基于java自带序列化之列的 - 如何传递数据
基于什么网络协议传输
java-rmi的远程协议
JSON-RPC协议
SOAP协议(web service 简单对下访问) - 如何表示方法
如何定义方法,如何在不同语言、不同系统环境中保证 方法签名唯一。
需要对接口描述定义语言有一个选型
再后面讲解了rpc的发展历史
CORBA的使用过于复杂,被抛弃
SOAP使用xml很简单,但是性能奇差
可以看出RPC想同时满足简单、普适、高性能是很难的
于是得出一个结论:
不存在完美的RPC框架
最近几年的RPC框架更倾向于往高层次、插件化发展。
即不再独立解决RPC的所有问题,而是提供一些扩展点由用户自己选择(比如dubbo)
可以任意切换json或者fastjson等序列化方式
可以切换传输协议等。
2 REST#
rest并不是一种远程调用协议, 他只能说是一种风格。
REST的传输效率提升潜力有限,但是可以简化调用。
2.1 REST核心概念(基于HTTP超文本传输协议)#
- 资源
资源指你希望获取或者修改的东西、信息本身,他的表现形式可以不同,但是里子是相同的 - 表征
就是表现资源的形式,用html还是pdf来返回 - 状态
指的是服务端对某次会话是否持有状态。
例如读下一篇文章时,当前文章id由服务端存储还是浏览器存储,这就是有状态和无状态的区别。 - 转移
就是服务端提供的行为逻辑, 通常叫做 资源的转移 - 统一接口
就是HTTP协议里提供的GET\HEAD\POST\PUT\DELETE\TRACE\OPTIONS这七种操作,通过这些操作触发转移 - 超文本驱动
浏览器的行为经常是通过服务端返回的url或者各种信息触发了驱动行为 - 自描述消息
为了方便客户端识别表征,返回类似于Content-Type等内容,方便用何种字符集处理
2.2 REST核心设计原则#
- 客户端与服务端分离
服务端不处理渲染, 由客户端来处理 - 无状态
尽可能希望服务端不要存储rest会话状态,达到分布式的高价值回报。
但是不太可能特别是客户端持有会话数量级很大的情况下,所以仍旧会持有一定状态 - 可缓存
服务端的应答中要直接或者间接告知客户端是否可以缓存,缓存多久 - 分层系统
客户端不需要知道是否真的连接到了最终的服务器
代表是CDN内容分发网络 - 统一接口
面向资源编程
系统设计时聚焦在资源而不是行为上
例如面向行为时, 登录就是login接口,注销就是logout接口
而面向资源时,登录就是PUT Session, 注销就是DELETE Session - 按需代码
客户端的代码可以有一部分让服务端发回进行装载。
2.3 REST的好处#
- 降低服务接口的学习成本
- 资源天然具有集合与层次接口
这样很多资源可以很容易组合在一起并让使用者想到接口url是什么
例如获取 用户 icyfenix的购物车中的第2本书,这个是有层次的,那么接口就是GET /user/icyfenix/cart/2 - REST绑定于HTTP协议,HTTP又是大家非常熟悉的
2.4 RMM(Richardson提出的restful成熟度模型)#
第0级:完全不rest#
提供的api定义里总是包含了各种动作,例如
/queryXXX
/applyXXX
类似于RPC的行为接口
坏处是一旦要提供其他对XXX的操作,必须重新编写接口,无法对XXX的查询能力进行复用!
第1级:开始引入资源的概念#
api的endpoint定义应该围绕名词+资源id而不是动词来定义。
POST /doctors/mjones 获取医生的档期
POST /schedules/{id} 触发对这个id的调度
第2级: 引入统一接口,映射到HTTP方法上#
上面的method都是POST,实际上可以把HTTP方法的method、返回码都给利用上
- 对一个资源的增加用POST,删除用DELETE,更新用PUT
- 依赖HTTP的返回码定义资源可能的异常情况。例如201代表创建成功,409代表冲突(被人抢先预约)
- 利用HTTP自带的认证和授权信息。
第3级:超文本控制,转移行为通过响应控制#
第2级里, 所有接口的定义仍然需要使用者自己查询文档来记忆和应用
实际上应该只需要一个操作起始入口, 例如获取医生的档期接口
这个接口要返回的body里,已经告知了对应资源的名称,例如档期资源的key就叫做schedules
那么就能马上知道下一个接口查询用schedules了!
这样代码里可以做好适配,当你要把档期的key名做修改时,客户端代码根本不用变动!
2.2.4 REST的不足和争议#
- restful面向资源编程只适合做CRUD,不适合过于复杂的业务逻辑
- 面向过程编程,以算法和处理过程为中心,这符合计算机世界中主流的交互方式
- 面向对象编程,将数据和对象行为统一起来,因为这符合现实世界的主流交互方式
- 面向资源编程,数据作为主体,行为看成统一接口,为了符合网络世界的主流交互方式
- rest不利于事务支持
作者不同意这个观点, 认为不会有阻碍,取决于系统的事务设计 - rest没有传输可靠性支持
虽然确实没有类似于重发等机制的保证,但rest接口一般尽可能要求幂等性,来做到应用代码做重发时可以不用担心重复的问题 - 缺少对资源做部分或者批量处理的能力
rest语义里不能涵盖这种情况,得定义特殊的接口或者参数,那么低3级里面就不能涵盖了。
相关思考#
基于REST的规范,调用者可以非常快速地理解自己需要的接口内容是什么样的,例如华为云当前的很多云服务公开接口都会基于REST理念进行开放, 并且各云服务的开放接口都会集成到API Explorer和华为云SDK中心供开发者直接调用,这些平台提供了丰富的接口文档和示例代码,帮助开发者更快地上手和使用 REST 接口。
相信未来REST 规范将会变得更加流行和普及。随着云计算和大数据技术的不断发展,REST 接口将会被广泛应用于各种领域,例如医疗、金融、电商等。REST 接口的开放性、可扩展性和易用性,将会为开发者带来更加高效、便捷和可靠的开发体验。