JSON RPC

偶然在 aria2 上看到了这个协议,平时我们都是用json来交换数据的,那么json RPC 是什么。

无状态且轻量级的远程过程调用(RPC)传送协议,其传递内容透过 JSON 为主。

相较于一般的 REST 透过网址(如 GET /user)调用远程服务器,JSON-RPC 直接在内容中定义了欲调用的函数名称(如 {“method”: “getUser”}),

这也令开发者不会陷于该使用 PUT 或者 PATCH 的问题之中。

我的看法

目前国内行业中普遍都是采用特别偷懒或不合理的做法

  • 请求全部使用 POST
  • 响应 永远都是 HTTP 200
  • 响应体里 一定要包装一层,而且有自己的错误码(好像也没人看/维护这个错误码)

在我看完 Json RPC 之后,我的评价是,直接解决国内开发问题

  1. 请求全部使用 POST,jsonprc: 只有一个 POST 接口, 所谓的接口安全 直接解决
  2. 响应 永远都是 HTTP 200:json rpc 定义了一部分错误码,而且和 http 的 status 完全错开 并且差异很大,这太棒了
  3. 响应体里 一定要包装一层,而且有自己的错误码: 请求体和响应体都是固定格式包一层的

此外的优点:

  • 异构,不管是什么语言,只要能发http请求,都能上
  • 无状态
  • json 传输
  • 不需要额外的组建和编译过程(轻量)
  • 不依赖某个特定的传输协议

太完美了。国内开发的福音啊 完全是。但是 为什么没有普及 我也是很难理解。。。

Code Sample

python ver.

Server side

依赖:

  • flask pip install flask
  • flask pip install jsonrpc
import json

from flask import Flask, request
from jsonrpc import JSONRPCResponseManager, dispatcher

app = Flask(__name__)

@app.route("/")
def hello():
    return {"status": "UP"}

@app.route("/jsonrpc", methods=['POST'])
def application():
    # Dispatcher is dictionary {<method_name>: callable}
    dispatcher["echo"] = lambda s: s
    dispatcher["add"] = lambda a, b: a + b

    // get json(but dict type)
    payload = request.get_json()

    // if null return error.
    if (payload == None):
        return {"error": {"code": 0, "message": "Request error"}, "id": 0, "jsonrpc": "2.0"}

    // json.dumps to json, then handle it.
    response = JSONRPCResponseManager.handle(json.dumps(payload), dispatcher)

    return response.json

@dispatcher.add_method
def foobar(**kwargs):
    return kwargs["foo"] + kwargs["bar"]

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

Client Side

import http.client
import json

def main():
    # Example echo method
    payload = {
        "method": "foobar",
        "params": {"foo": "json", "bar": "-rpc"},
        "jsonrpc": "2.0",
        "id": 3,
    }

    json_data = json.dumps(payload)
    headers = {'Content-type': 'application/json'}

    http_connection = http.client.HTTPConnection(host="localhost", port=8000)
    http_connection.request(url="/jsonrpc", body=json_data, method= "POST" ,headers= headers)
    resp = http_connection.getresponse()

    print(resp.read().decode())

if __name__ == "__main__":
    main()

overall

Json RPC 是一个很好的协议,我希望在将来能够看到国内“大厂”普遍使用,我自己的某部分应用再接下来也会开始使用。

ref: