Python语言下的RPC开发

一、httpserver实现rpc

 1、server.py

from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qsl
import json

host = ('', 8000)


class UserHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        """处理get请求"""
        parse_url = urlparse(self.path)  # 处理请求地址
        qs = dict(parse_qsl(parse_url.query))  # 获取请求地址中携带的参数
        uid = int(qs.get("uid", 0))  # 比如携带的参数是uid
        self.send_response(200)  # 设置响应码
        self.send_header('Content-type', 'application/json')  # 设置响应头
        self.end_headers()
        if uid == 1:  # 写入响应体
            self.wfile.write(
                json.dumps(
                    {
                        "username": "bily",
                        "gender": "male"
                    }
                ).encode("utf-8")
            )


if __name__ == '__main__':
    server = HTTPServer(host, UserHandler)
    server.serve_forever()

2、client.py

import requests

# 请求
res = requests.get(url="http://127.0.0.1:8000/?uid=1")
print(res.text)

上面其实就是实现了一个http的服务,通过http请求来完成客户端对于服务端的请求,但是显然有一些不满足远程过程调用的要求,比如客户端的调用应该向本地调用一样,而不是发送请求,那么我们可以将客户端进行一下封装:

import requests


class Client:

    def __init__(self, url):
        self.url = url

    def get_user(self):
        res = requests.get(url=self.url)
        return res.text


c = Client("http://127.0.0.1:8000/?uid=1")
# 模拟本地调用
res = c.get_user()
print(res)

可以看到通过封装后调用get_user方法,屏蔽了底层一些网络协议的细节。

二、基于xml实现rpc

 1、server.py

from xmlrpc.server import SimpleXMLRPCServer


class Calculate:

    def add(self, x, y):
        return x + y


obj = Calculate()

server = SimpleXMLRPCServer(("localhost", 8000))

# 将实例注册到rpc server
server.register_instance(obj)
server.serve_forever()

2、client.py

from xmlrpc import client

c = client.ServerProxy("http://localhost:8000")
# 远程调用服务端的函数
res = c.add(3, 5)
print(res)

三、基于json实现rpc

基于xml是通过xml来进行数据的编码和解码,不过经常用到的的序列化和反序列化的还有json,那么如何通过json来实现rpc呢?

需要借助于jsonrpclib这个库,安装:

pip install jsonrpclib-pelix

1、server.py

from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer


class Calculate:

    def sub(self, x, y):
        return x - y


server = SimpleJSONRPCServer(("localhost", 8000))
# 注册函数
server.register_function(lambda x, y: x + y, "add")
# 注册实例
obj = Calculate()
server.register_instance(obj)
server.serve_forever()

2、client.py

import jsonrpclib

client = jsonrpclib.ServerProxy("http://localhost:8000")
res1 = client.add(1, 2)
res2 = client.sub(3, 5)
print(res1)
print(res2)

四、 基于zerorpc实现rpc

zerorpc是利用 zeroMQ消息队列 + msgpack 消息序列化(二进制) 来实现类似 grpc 的功能,跨语言远程调用。

zerorpc可以以编程方式或从命令行使用。它带有一个方便的脚本“zerorpc”,允许:

  • 无需修改任何代码即可公开 Python 模块
  • 通过命令行远程调用这些模块

不过它会依赖一些库,比如:msgpack-python, pyzmq, future, greenlet, gevent

所以使用它之前需要先进行安装:

pip install zerorpc

(一)一元调用

1、server.py

import zerorpc


class Calculate:

    def add(self, a, b):
        return a + b


server = zerorpc.Server(Calculate())
server.bind("tcp://0.0.0.0:8000")
server.run()

2、client.py

import zerorpc

client = zerorpc.Client()
client.connect("tcp://127.0.0.1:8000")
res = client.add(2, 3)
print(res)

(二)流式响应

1、server.py

import zerorpc


class StreamingNum:
    @zerorpc.stream
    def streaming_range(self, start, end, step):
        return range(start, end, step)  # 返回的是一个生成器


server = zerorpc.Server(StreamingNum())
server.bind("tcp://0.0.0.0:8000")
server.run()

2、client.py

import zerorpc

client = zerorpc.Client()
client.connect("tcp://127.0.0.1:8000")

res = client.streaming_range(1, 10, 2)
for i in res:
    print(i)

 

上一篇:Android 不通过parent实现样式继承


下一篇:2017沈阳站(重温经典)