Peter 自己是一个多年的 Web 开发者,每天操作服务器都是发普通的 HTTP 请求,生活是美满幸福的,但是到区块链这边再看,本地操作服务器都是用 JSON-RPC 了,类似 bitcoin, 以太坊,包括 nervos 都是用 JSON-RPC 。本文就是献给跟我知识背景差不多的,理解什么是 HTTP 请求,想要多了解一下什么是 JSON-RPC 的朋友们。

什么是 RPC ?

先说什么是 RPC 。RPC 是 Remote Procedure Call ,字面意思是远程过程调用。但是说白了就是从本地机器去执行服务器上的一个函数。所以说 RPC 指的是一类日常的操作,是个很宽泛的概念。

首先说 HTTP 请求本身也可以看做是 RPC 的一种具体形式。HTTP 请求也一样是可以从本地发一个信号到服务器,服务器上执行某个函数,然后返回一些信息给客户端。所以宽泛而言,HTTP 请求本身就是一种 RPC 的形式,二者不是同一个层面的概念。但是网上另外一种说法也很有道理,有人会拿 HTTP 请求和 RPC 作为平行概念来对比,说 HTTP 好比普通话,而 RPC 是各地方言,其实这里的 RPC 精确的来讲指的是开发者自己手写的某种 RPC 形式,所以才能跟 HTTP 形成平行关系。这句话可以理解为 HTTP 请求是如此的常见,以至于如果我们自己想开放自己机器的部分功能给任意的人用,那么使用 HTTP API 的形式是非常合适的,因为 HTTP 请求是大家都经常使用的方式。而很多时候,对于公司内部的两台机器之间,大家会按照实际需要去自定制一套 RPC ,这样做的好处是灵活高效,但是坏处就是没有通用性,所以是一种方言。

RPC 的灵活性和自定制性很强,所以学习使用 RPC 可以从具体的协议和框架入手。JSON-RPC 就是是一套 RPC 协议,使用 JSON 作为数据类型,最后一部分咱们详细聊。谷歌的 gRPC 是一个 RPC 框架,底层通信协议是基于 HTTP2.0 的。RPC 也可以不走 HTTP 协议,而直接在 TCP 协议上去做定制,去获得更大的效率和灵活性。

所以总结起来 RPC 是一个很宽泛的概念,指的是从网络上的一台机器去执行另外一台机器上的代码。HTTP 请求,可以认为是 RPC 的一种具体形式。

HTTP 请求和 RPC 的异同

再来看看 HTTP 请求和 RPC 有什么相同点和不同点。再次提醒,这里的 RPC 指的其实就是大家使用 RPC 的各种常见形式的统称。下面的各种比较可能并不精确,但是的确涵盖了最主流的观点,可以帮助大家形成一个明确的感性认识。

先看相同点。HTTP 请求和 RPC 的相同点是同样都具有请求和响应。二者的基本过程是一样的,首先从客户端机器发出请求,服务器收到之后执行某段代码,然后把运算结果或者是报错信息作为响应,返回给客户端。

再看差别。首先一大差别:HTTP 请求往往围绕资源,而 RPC 的请求往往围绕一个动作。比如一个常见的 HTTP 请求是 GET indexPOST posts,分别表示请求首页,或者发布一篇文章。而用 RPC 执行相同的任务,就是指定一个动作,说白了就是直接给出函数名,例如 get_index() 或者 create_post() 。再说第二个差别: HTTP 请求的服务器上,通常是安装了 nginx 或者阿帕奇这样的 HTTP 服务器软件的,而提供 rpc 的服务器显然不一定需要安装这些软件。RPC 的思想是把本地函数映射到 API,也就是每一个公开给客户端的 API 对应的是一个服务器上函数。例如,服务器上运行的 C++ 程序中有个 get_index 函数,客户端发请求的时候就指名道姓的呼叫这个函数即可。

总之,HTTP 请求和 RPC 相同点明显,差异也算很明显。

JSON-RPC 简介

通常讲一个东西给朋友听,最好的方式是 SHOW DONT TELL ,也就是别光说,看个例子就明白了。所以最后一部分咱们关注一下 JSON-RPC 。官方的定义是:JSON-RPC 是一个无状态的轻量级的 RPC 协议。什么是 JSON 什么是无状态,这些都是 HTTP 的基本知识了,我们这里不展开。协议的详情我们可以直接去看 SPEC 文档:https://www.jsonrpc.org/specification 。这里我们着重关注请求和响应的格式,从而印证一下之前得出的一些结论。

--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}

SPEC 文档上可以看到请求和响应一些具体的例子。例如从其中一个可以看到, method 也就是方法这个字段的值是 subtract ,也就是减去。这个显然跟普通的 HTTP 请求格式不一样,不是 GET 某个资源的形式,而是符合 RPC 的基本特征,看上去就是一个函数名。后面 params 一项后面跟一个数组,里面有两个数,42 和 23 。服务器端的函数接收到这两个数字之后,会把执行 subtract 函数,把这两个数作为 subtract 的参数,运算结果是19。这个结果会作为响应数据返回给客户端。

这里,不管是请求还是响应数据的格式,都满足 JSON 规范的,这就是 JSON-RPC 名字的由来了。

总结

本文的目的就是让大家形成对 HTTP 请求和 RPC 的感性上的区分,主体内容就是这些了。总结起来说,RPC 是远程过程调用的意思,可以简单理解为从我的机器操作网络上另外一台机器,去执行它上面的某个函数。所以 RPC 本身是一类操作的统称,是一个比较宽泛的概念。HTTP 请求,也可以认为是 RPC 的一种形式。实际中人们常说的 RPC ,通常指自己手写的某种 RPC 的实现方式,区别于 HTTP 请求的一大特点是会直接呼叫远端的函数名。最后,通过学习 JSON-RPC 的这个具体协议,印证一下我们的这些结论。