什么是RPC
RPC(Remote Procedure Call Protocol)-- 远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络协议的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
什么是gRPC
gRPC 是Google开源的一款高性能的 RPC 框架,它基于 ProtoBuf 序列化协议进行开发,支持多种开发语言(Golang、Python、Java、C/C++等)。gRPC 提供了一种简单的方法来定义服务,同时客户端可以充分利用 HTTP/2 stream 的特性,从而有助于节省带宽、降低 TCP 的连接次数、节省CPU的使用等。
本文参考官方文档[grpc.html],以及gRPC的GitHub开源项目grpc/grpc。并通过一个小demo展示框架用法。
安装gRPC及gRPC工具
pip install grpcio
pip install grpcio-tools
grpcio-tools包含了protobuf的编辑工具 protoc,用来根据 .proto 服务定义生成服务器端和客户端代码。
自定义 gRPC 接口
假定这里我们需要定义一个数据接收服务Receiver,用来接收客户端传递给服务器端的数据。
syntax = "proto3";
import "google/protobuf/struct.proto";
// 服务定义
service Receiver {
rpc receive (Event) returns (Reply) {}
}
// 接收消息定义
message Event {
string appid = 1;
int32 xwhen = 2;
string xwho = 3;
string xwhat = 4;
google.protobuf.Struct xcontext = 5;
}
// 返回消息定义
message Reply {
int32 status = 1;
string message = 2;
}
编译 proto 文件生成服务接口
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./receiver.proto
这里会生成两个python文件:
receiver_pb2.py
receiver_pb2_grpc.py
编写Server端代码
# _*_ coding: utf-8 _*_
import grpc
import receiver_pb2
import receiver_pb2_grpc
import time
from concurrent import futures
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class Receiver(receiver_pb2_grpc.ReceiverServicer):
# 重写父类方法,返回消息
def receive(self, request, context):
print('request:', request)
return receiver_pb2.Reply(message='Hello, %s!' % request.xwho)
if __name__ == '__main__':
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
receiver_pb2_grpc.add_ReceiverServicer_to_server(Receiver(), server)
server.add_insecure_port('[::]:50051')
server.start()
print('server start...')
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop()
编写client端代码
# _*_ coding: utf-8 _*_
import grpc
import receiver_pb2
import receiver_pb2_grpc
from google.protobuf import struct_pb2
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = receiver_pb2_grpc.ReceiverStub(channel)
# 自定义struct结构
struct = struct_pb2.Struct()
struct['idfa'] = 'idfa1'
struct['amount'] = 123
response = stub.receive(receiver_pb2.Event(xwhat='install', appid='fuckgod', xwhen=123, xwho='jerry', xcontext=struct))
print("client status: %s received: %s" % (response.status, response.message))
if __name__ == '__main__':
run()
测试流程
(1)启动server:python server.py &
(2)运行client.py发送消息
server输出:
server start...
request:
appid: "fuckgod"
xwhen: 123
xwho: "jerry"
xwhat: "install"
xcontext {
fields {
key: "amount"
value {
number_value: 123.0
}
}
fields {
key: "idfa"
value {
string_value: "idfa1"
}
}
}
client输出:
client status: 0 received: Hello, jerry!
表示测试成功。
参考:
grpc /grpc/grpcgrpc/grpc