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()
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方法,屏蔽了底层一些网络协议的细节。
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()
from xmlrpc import client c = client.ServerProxy("http://localhost:8000") # 远程调用服务端的函数 res = c.add(3, 5) print(res)
基于xml是通过xml来进行数据的编码和解码,不过经常用到的的序列化和反序列化的还有json,那么如何通过json来实现rpc呢?
需要借助于jsonrpclib这个库,安装:
pip install jsonrpclib-pelix
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()
import jsonrpclib client = jsonrpclib.ServerProxy("http://localhost:8000") res1 = client.add(1, 2) res2 = client.sub(3, 5) print(res1) print(res2)
zerorpc是利用 zeroMQ消息队列 + msgpack 消息序列化(二进制) 来实现类似 grpc 的功能,跨语言远程调用。
zerorpc可以以编程方式或从命令行使用。它带有一个方便的脚本“zerorpc”,允许:
不过它会依赖一些库,比如:msgpack-python, pyzmq, future, greenlet, gevent
所以使用它之前需要先进行安装:
pip install zerorpc
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()
import zerorpc client = zerorpc.Client() client.connect("tcp://127.0.0.1:8000") res = client.add(2, 3) print(res)
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()
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)