RPC API介绍与实现

Posted Htojk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RPC API介绍与实现相关的知识,希望对你有一定的参考价值。

简介:RPC(Remote Procedure Call,远程过程调用)是一种通信协议,用于使远程计算机之间的程序能够相互调用。与本地调用类似,远程调用的过程是将一个请求发送到远程计算机上,远程计算机执行该请求并将结果返回给本地计算机。RPC常用于构建分布式系统和微服务架构中的服务之间的通信。

RPC的哲学思想可以概括为:

  1. 透明性:RPC应该使远程过程调用看起来像本地调用一样简单和透明。调用者不需要了解远程过程调用的细节,只需要像调用本地函数一样调用远程函数。

  2. 互操作性:RPC应该支持不同编程语言和不同操作系统之间的相互通信,使得分布式系统可以跨平台和跨语言进行通信。

  3. 高效性:RPC应该尽可能地减少网络传输和处理时间,提高系统的性能和吞吐量。

  4. 可靠性:RPC应该能够处理网络故障和其他错误,保证系统的可靠性和稳定性。

python代码实现

下面是一个简单的Python代码实现RPC接口的示例,使用了Pyro4库。

安装Pyro4库

pip install pyro4

Pyro4库简介

        Pyro4是一个用于Python语言的分布式对象中间件,它可以让Python对象在分布式环境中进行远程调用,从而实现分布式系统的构建。

        Pyro4提供了很多有用的功能,比如动态对象代理、异步调用、对象序列化等。它支持多种网络协议,包括TCP、Unix域套接字、ZeroMQ等,还提供了可扩展的安全模型,包括基于SSL/TLS的加密、基于密码的身份验证等。

        Pyro4介绍以及用例实现

定义RPC服务接口

# example_service.py
import Pyro4

@Pyro4.expose
class ExampleService(object):
    def say_hello(self, name):
        return "Hello, !".format(name)

实现RPC服务

# example_service_server.py
import Pyro4
from example_service import ExampleService

def main():
    example_service = ExampleService()
    daemon = Pyro4.Daemon()
    ns = Pyro4.locateNS()
    uri = daemon.register(example_service)
    ns.register("example.service", uri)
    print("Ready.")
    daemon.requestLoop()

if __name__ == "__main__":
    main()

实现RPC客户端 

# example_service_client.py
import Pyro4

uri = Pyro4.locateNS().lookup("example.service")
example_service = Pyro4.Proxy(uri)

print(example_service.say_hello("John"))

 这个示例实现了一个简单的RPC服务,客户端可以调用服务端的say_hello方法来获取一个问候语。在实际应用中,可以将服务拆分成不同的微服务,使用RPC协议来实现微服务之间的通信。

应用范例,在odoo当中的jsonRPC接口

1、定义一个jsonRPC服务端

# my_module/controllers/main.py
from odoo import http
from odoo.http import JsonRequest, request, Response

class MyController(http.Controller):
    @http.route('/my_module/rpc', type='json', auth='none', csrf=False)
    def my_rpc_method(self, method=None, params=None, id=None):
        if method == 'hello':
            name = params[0]
            return 'result': f'Hello, name!'
        else:
            error = 'code': -32601, 'message': 'Method not found', 'data': 'method': method
            return 'error': error, 'id': id

2、实现一个jsonRPC客户端

# my_module/client.py
import requests
import json

url = "http://localhost:8069/my_module/rpc"

def jsonrpc_request(method, params):
    payload = 'jsonrpc': '2.0', 'method': method, 'params': params, 'id': 1
    headers = 'Content-type': 'application/json'
    response = requests.post(url, data=json.dumps(payload), headers=headers)
    if response.status_code == 200:
        result = response.json().get('result')
        if result is not None:
            return result
        else:
            error = response.json().get('error')
            if error is not None:
                raise Exception(f"JSON-RPC error: error.get('message')")
    else:
        raise Exception(f"HTTP error: response.status_code")

result = jsonrpc_request('hello', ['John'])
print(result)  # output: 'result': 'Hello, John!'

在上述代码中,my_rpc_method方法是jsonRPC服务端的实现,使用@http.route装饰器将该方法映射为一个HTTP接口。jsonrpc_request方法是jsonRPC客户端的实现,它构造了一个符合jsonRPC协议的HTTP请求,并将请求发送到jsonRPC服务端。客户端通过判断响应的状态码和内容来确定jsonRPC通信的成功与否,并获取结果或抛出异常。

总的来说,Odoo的jsonRPC实现比较简单,主要依赖于Python内置的JSON库和第三方的requests库来实现JSON编解码和HTTP通信功能。

.NET 开源项目 StreamJsonRpc 介绍[上篇]

StreamJsonRpc 是一个实现了 JSON-RPC 通信协议的开源 .NET 库,在介绍 StreamJsonRpc 之前,我们先来了解一下 JSON-RPC。

JSON-RPC 介绍

JSON-RPC 是一个无状态且轻量级的远程过程调用(RPC)协议,其使用 JSON(RFC 4627)作为数据格式。

目前 JSON-RPC 的版本已发展到 2.0,JSON-RPC 2.0 与 1.0 的约定规范是不一样的。2.0 包含一个名为 jsonrpc 且值为 2.0 的成员,而 1.0 版本是不包含的。所以我们可以很容易在两个版本间区分出 2.0。

JSON-RPC 在客户端与服务端之间交换的所有成员名应是区分大小写的,函数、方法、过程都认为是可互换的。客户端被定义为请求对象的来源及响应对象的处理程序;服务端被定义为响应对象的起源和请求对象的处理程序。

请求对象

发送一个请求对象至服务端代表一个 RPC 调用,JSON-RPC 2.0 规定一个请求对象包含下列成员:

  • jsonrpc:指定 JSON-RPC 协议版本的字符串,必须准确写为“2.0”。

  • method:包含所要调用方法名称的字符串,以 rpc 开头的方法名,用英文句号连接的为预留给 rpc 内部的方法名及扩展名,且不能在其他地方使用。

  • params:调用方法所需要的结构化参数值,该成员参数可以被省略。

  • id:已建立客户端的唯一标识,值必须包含一个字符串、数值或 NULL 空值。如果不包含该成员则被认定为是一个通知。该值一般不为 NULL,若为数值则不应该包含小数。

没有包含 id 成员的请求对象为通知,作为通知的请求对象表明客户端对服务端响应不感兴趣,服务端可以不响应请求对象给客户端。

下面是几个请求对象的 JSON 结构示例(“-->”表示发送,“<--”表示响应,下同):

--> { "jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1 }
--> { "jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}
--> {"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]} // 通知

响应对象

当客户端发起一个 RPC 调用时,除通知之外,服务端都必须回复响应。响应也表示为一个 JSON 对象,使用以下成员:

  • jsonrpc:指定 JSON-RPC 协议版本的字符串,必须准确写为“2.0”。

  • result:调用成功时响应给客户端的结果,当调用发生错误时可以不包含该成员。

  • error:调用发生错误时返回给客户端的错误信息,在调用失败时必须包含该成员。

  • id:对应请求对象的“id”,其值必须与请求对象中的“id”值一致。

响应对象必须包含 result 或 error 成员之一。

响应对象的 error 成员的结构包含下列成员:

  • code:使用数值表示该异常的错误类型,必须为整数。、

  • message:对该错误的简单描述字符串,该描述应尽量限定在简短的一句话。

  • data:包含关于错误的附加信息,可忽略。

其中 -32768 至 -32000 为保留的预定义错误代码,各保留错误代码的含义请查看文末参考链接[1]。

下面是几个响应对象的 JSON 结构示例:

<-- {"jsonrpc": "2.0", "result": 19, "id": 1}
<-- {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"}
<-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": null} // 无效调用

批量调用

当需要同时发送多个请求对象时,客户端可以发送一个包含所有请求对象的数组。

当批量调用的所有请求对象处理完成时,服务端则需要返回一个包含相对应的响应对象数组。每个响应对象都应对应每个请求对象,除非是通知的请求对象。服务端可以并发的,可以以任意顺序和任意宽度并行处理这些批量调用。而客户端应该是基于各个响应对象中的 id 成员来匹配对应的请求对象。

若批量调用没有需要返回的响应对象,则服务端不需要返回任何结果。

下面是一个批量请求及响应的 JSON 结构示例:

--> [
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
{"foo": "boo"},
{"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", "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"}
]

当批量请求对象都是通知时,服务端不需要返回结果。

StreamJsonRpc 库介绍

github.com/microsoft/vs-streamjsonrpc

StreamJsonRpc 可以在 Stream、WebSocket 或 System.IO.Pipelines 管道上工作,独立于底层传输。除了包含 JSON-RPC 规范所需的特性外,它额外还有如下优点:

  • 请求取消

  • .NET 事件作为通知

  • 动态客户端代理生成

  • 支持紧凑的 MessagePack 二进制序列化

  • 易于实现插件式架构的消息处理和格式化

使用 StreamJsonRpc 主要有四个基本步骤:建立 JSON-RPC 连接、发送 RPC 请求、接收 RPC 请求、断开连接。

这一篇主要介绍一些预备知识,下一篇将通过示例演示并详细介绍 StreamJsonRpc 的使用,敬请期待!

参考: 
[1].jsonrpc.org/specification 

[2].github.com/microsoft/vs-streamjsonrpc

以上是关于RPC API介绍与实现的主要内容,如果未能解决你的问题,请参考以下文章

网络协议 22 - RPC 协议(下)- 二进制类 RPC 协议

网络协议-RPC协议

网络协议-RPC协议

RPC介绍

RPC简单介绍

我对RPC的理解