由于RPC使用形式上和调用同一个进程内存空间的函数或方法一样,因此需要解决以下3个问题:
HTTP请求本身也可以看做是RPC的一种具体形式。HTTP请求也一样是可以从客户端发一个信号到服务端,服务端上执行某个函数,然后返回一些信息给客户端。HTTP请求非常常见,如果我们自己想开放自己机器的部分功能给任意的人用,那么使用HTTP API的形式是非常合适的,因为HTTP请求是大家都经常使用的方式。而很多时候,对于公司内部的两台机器之间,大家会按照实际需要去自定制一套RPC,这样做的好处是灵活高效,但是坏处就是没有通用性。
HTTP和RPC异同:
JSON-RPC协议简介
JSON-RPC是一个无状态且轻量级的RPC协议,其传输内容以JSON方式,相对于一般的HTTP请求通过URI调用远程服务器,JSON-RPC直接在内容中定义了要调用的函数名称(如 {“method”: “getUser”}),对于开发者来说非常的方便。
Bitcoin和Ethereum都支持JSON-RPC通过客户端直接调用节点上的函数或方法。
注意: 以rpc开头的方法名预留作为系统扩展,且必须不能用于其他地方。
JSON-RPC请求
JSON-RPC 2.0和1.0之间一些差异,我们这里介绍2.0的使用,一个JSON-RPC的请求必须包含以下4个字段。
JSON-RPC响应
当发起一个RPC调用时,除通知之外服务端都必须有响应,响应表示为一个JSON对象包含以下几个字段。
JSON-RPC错误码
JSON-RPC示例
1. 带索引数组参数的rpc调用
--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}
2. 带关联数组参数的rpc调用
--> {"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}
<-- {"jsonrpc": "2.0", "result": 19, "id": 3}
3. rpc批量调用
--> [{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"},
{"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"},
{"jsonrpc": "2.0", "method": "get_data", "id": "9"}]
<-- [{"jsonrpc": "2.0", "result": 7, "id": "1"},
{"jsonrpc": "2.0", "result": 19, "id": "2"},
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null},
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "5"},
{"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"}]
1. 调用了未定义的方法的rpc调用
--> {"jsonrpc": "2.0", "method": "foobar", "id": "1"}
<-- {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"}
2. 包含无效json的rpc调用
--> {"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz]
<-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": null}
3. 无效请求对象的rpc调用
--> {"jsonrpc": "2.0", "method": 1, "params": "bar"}
<-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null}
四、RPC与HTTP的使用场景区分
HTTP可读性比较好,HTTP请求工作在应用层,封装比较复杂,可用信息量低,这是为可读性做的牺牲。
但是在系统内的服务A调用服务B的过程属于内部的事情,牺牲可读性提升效率是可取的。基于这种思路,RPC产生了。
大部分RPC是基于TCP实现的(提高数据传输效率),当然也可以使用HTTP实现。
从传输速度上来看,因为HTTP封装的数据量更多所以数据传输量更大,所以RPC的传输速度是比RESTFUL更快的。
因为HTTP协议是各个框架都普遍支持的。在toC情况下,因为不知道情况来源的框架、数据形势是什么样的,所以在网关可以使用Restful利用http来接收。而在微服务内部的各模块之间因为各协议方案是公司内部自己定的,所以知道各种数据方式,可以使用TCP传输以使各模块之间的数据传输更快。所以可以在网关和外界的数据传输使用RESTFUL,微服务内部的各模块之间使用RPC。
RESTFUL的API的设计上是面向资源的,对于同一资源的获取、传输、修改可以使用GET、POST、PUT来对同一个URL进行区别,而RPC通常把动词直接体现在URL上。
RPC可以使用自定义的TCP协议,可以让请求报文体积更小,或者使用HTTP2协议,也可以很好的减少报文的体积,提高传输效率。
一般来说,RPC服务主要是针对大型企业的,而HTTP服务主要是针对小企业的,因为RPC效率更高,而HTTP服务开发迭代会更快。
使用RPC还是使用HTTP,需要对整个项目进行完整地评估,从而比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。一定不要为了使用RPC而每个项目都用RPC,而是要因地制宜,具体情况具体分析。
相关内容:
RPC框架由来、发展总结
远程过程调用
【基础】RPC、JSON-RPC和HTTP区别
RPC服务和HTTP服务对比