rpc
1. 面临的问题
a. Call 的 id 映射
b. 序列化和反序列化 json 序列化/反序列化
c. 网络传输
http2.0 ==> rpc
### 自己实现的 demo 级别的 rpc 封装
提供 add 方法方
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 11:41 AM
import json
from urllib.parse import urlparse, parse_qsl
from http.server import HTTPServer, BaseHTTPRequestHandler
host = ('', 8003)
class AddHandler(BaseHTTPRequestHandler):
def do_GET(self):
parsed_url = urlparse(self.path)
qs = dict(parse_qsl(parsed_url.query))
a = int(qs.get("a", 0))
b = int(qs.get("b", 0))
self.send_response(200)
self.send_header("content-type", "application")
self.end_headers()
self.wfile.write(json.dumps({
"result": a+b
}).encode("utf-8")
)
if __name__ == '__main__':
server = HTTPServer(host, AddHandler)
print("启动 rpc 服务...")
server.serve_forever()
远程调用客户端
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 11:47 AM
import requests
import json
class Client:
def __init__(self, url):
self.url = url
def add(self, a, b):
res = requests.get(f"{self.url}/?a=1&b=2")
return json.loads(res.text).get("result")
if __name__ == '__main__':
client = Client("http://127.0.0.1:8003")
print(client.add(1,2))
# 基于 xml 的 rpc py 库
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 12:33 PM
from xmlrpc.server import SimpleXMLRPCServer
class Calculate:
def add(self, x, y):
return x+y
def multiply(self, x, y):
return x*y
def substract(self, x, y):
return x-y
def divide(self, x, y):
return x/y
if __name__ == '__main__':
cal = Calculate()
server = SimpleXMLRPCServer(("localhost", 8014))
# 将实例注册给 rpc server
server.register_instance(cal)
print("Listening on port 8014")
server.serve_forever()
-------=========-----------
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 12:37 PM
from xmlrpc import client
class RPCClient:
def __init__(self, url):
self.client = client.ServerProxy(url)
def add(self, x, y):
return self.client.add(x, y)
if __name__ == '__main__':
rpc_client = RPCClient("http://localhost:8014")
ret = rpc_client.add(1, 2)
print(ret)
json-rpc ==》 jsonrpclib 支持并发, 支持 HTTPS
zeromq 这个 rpc 框架 是否支持 多语言?
zerorpc == zeroMQ + msgpack(消息序列化二进制)来实现 类似 grpc 的 功能
通信模式 ROUTER-DEALER 模拟 grpc 的请求-响应式 和 应答流式
此外他还支持 PUB-SUB 通信模式的远程调用
zerorpc 实际上依赖 msgpack-python, pyzmq, future, greenlet, gevent
支持 python + nodejs
// go 的 rpc 入门级 demo
package main
import (
"fmt"
"net"
"net/rpc"
)
type HelloService struct {
}
// 固定格式如下
func(service *HelloService) Hello(request string, reply *string) error{
// 返回值是通过修改 reply 的值
*reply = "hello, "+request
return nil
}
func main(){
//1. 实例化 server
listen, err := net.Listen("tcp", ":1234")
if err != nil{
fmt.Println("")
}
//2. 注册处理逻辑 handler
_ = rpc.RegisterName("HelloService", &HelloService{})
//3. 启动服务
accept, err := listen.Accept()
rpc.ServeConn(accept)
}
package main
import (
"fmt"
"net/rpc"
)
func main(){
client, err := rpc.Dial("tcp", "localhost:1234")
if err != nil{
fmt.Println("连接失败...", err)
}
var reply string
client.Call("HelloService.Hello", "frank", &reply)
fmt.Println("reply: ", reply)
}