2.2 REST设计风格

很多人会拿REST与RPC相比较,其实,REST无论是在思想上、在概念上,还是在使用范围上,与RPC都不尽相同,充其量只能算是有一些相似,应用会有一部分重合之处,但本质上并不是同一类型的东西。

REST与RPC在思想上差异的核心是抽象的目标不一样,即面向过程的编程思想与面向资源的编程思想两者之间的区别。面向过程编程、面向对象编程想必大家都听说过,但什么是面向资源编程呢?这个问题等介绍完REST的特征之后我们再细说。

REST与RPC在概念上的不同是指REST并不是一种远程服务调用协议,甚至可以把定语也去掉,它就不是一种协议。协议都带有一定的规范性和强制性,最起码也有一个规约文档,譬如JSON-RPC,哪怕再简单,也有《JSON-RPC规范》[1]来规定协议的格式细节、异常、响应码等信息,但是REST并没有定义这些内容,尽管有一些指导原则,但实际上并不受任何强制的约束。常有人批评某个系统接口“设计得不够RESTful”,其实这句话本身就有些争议,REST只能说是风格而不是规范、协议,并且能完全符合REST所有指导原则的系统也是不多见的,这一点我们同样将在后文中详细讨论。

至于使用范围,REST与RPC作为主流的两种远程调用方式,在使用上确有重合,但重合区域的大小就见仁见智了。上一节提到了当前的RPC协议框架都各有侧重点,并且列举了RPC的一些发展方向,如分布式对象、提升调用效率、简化调用复杂性,等等。这里面分布式对象的应用与REST可以说是毫无关联;而能够重视远程服务调用效率的应用场景,就基本排除了REST应用得最多的供浏览器端消费的远程服务,因为以浏览器作为前端,对于传输协议、序列化器的可选择性不多,哪怕想要更高效率也有心无力。而在移动端、桌面端或者分布式服务端的节点之间通信这一块,REST虽然有宽阔的用武之地,只要支持HTTP就可以用于任何语言之间的交互,不过通常都会以网络没有成为性能瓶颈为使用前提,在需要追求传输效率的场景里,REST提升传输效率的潜力有限,死磕REST又想要好的网络性能,一般不会有好的效果;对追求简化调用的场景——前面提到的浏览器端就属于这一类的典型,众多RPC里也只有JSON-RPC有机会与REST竞争,其他RPC协议与框架,哪怕能够支持HTTP协议,提供了JavaScript版本的客户端(如gRPC-Web),也只是具备前端使用的理论可行性,很少有实际项目把它们真正用到浏览器上。

尽管有着种种不同,REST与RPC还是引发了很频繁的比较与争论,这两种分别面向资源和过程的远程调用方式,就如同当年面向对象与过程的编程思想一样,非得分出高低不可。

[1] JSON-RPC 2.0规范地址:https://www.jsonrpc.org/specification。