python使用grpc服务调用的实例,grpc是一款高性能的开源RPC框架,出自Google公司,基于ProtoBuf序列化协议进行开发,支持多语言跨平台。其中grpc对HTTP/2协议的支持,使得在各种客户端服务的开发领域具有很好的发展。grpc提供了一种简单的方法来定义服务,同时客户端充分使用http2 stream的特征,从而有助于节省带宽、降低tcp的链接次数、节省cpu使用率。
安装相关安装包
pip install grpcio
pip install protobuf
pip install grpcio-tools
proto的中间信息定义模块,hello.proto文件
// [python quickstart](https://grpc.io/docs/quickstart/python.html#run-a-grpc-application)
// python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. helloworld.proto
// helloworld.proto
syntax = "proto3";
service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain(HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
string age = 2;
string money = 3;
}
message HelloReply {
string message = 1;
}
使用python继续生成服务文件,使得python服务调用使用:run_codegen.py
from grpc_tools import protoc
import os
files = os.listdir("./")
for f in files:
if ".proto" in f:
protoc.main((
'',
'-I.',
'--python_out=.',
'--grpc_python_out=.',
'{}'.format(f), ))
使用上述的代码,能够将proto文件解析生成,两个文件hello_pb2.py和hello_pb2_grpc.py, 其中hello_pb2.py主要是传输过程中的传输结构体,hello_pb2_grpc.py是通信过程中的服务传输,主要提供服务和调用服务使用。
服务端的代码,提供服务,要实现proto中service的服务接口,重写处理函数,然后再grpc服务中调用重写后的实例化对象。这样创建的grpc服务器就可以实现自定义的proto传输服务了
from concurrent import futures
import time
import grpc
import hello_pb2
import hello_pb2_grpc
# 实现 proto 文件中定义的 GreeterServicer
class Greeter(hello_pb2_grpc.GreeterServicer):
# 实现 proto 文件中定义的 rpc 调用
def SayHello(self, request, context):
return hello_pb2.HelloReply(message = 'hello {msg}, {m2}'.format(msg = request.name, m2=request.age))
def SayHelloAgain(self, request, context):
return hello_pb2.HelloReply(message='hello {msg}'.format(msg = request.name))
def serve():
# 启动 rpc 服务
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
hello_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(60*60*24) # one day in seconds
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
客户端的代码就是基于生成的hello_pb2.py的传输协议,进行和服务端通信。
import grpc
import hello_pb2
import hello_pb2_grpc
def run():
# 连接 rpc 服务器
channel = grpc.insecure_channel('localhost:50051')
# 调用 rpc 服务
stub = hello_pb2_grpc.GreeterStub(channel)
a = hello_pb2.HelloRequest()
a.name = 'czl'
a.age = '12'
a.money = '1212'
response = stub.SayHello(a)
print("Greeter client received: " + response.message)
response = stub.SayHelloAgain(hello_pb2.HelloRequest(name='daydaygo'))
print("Greeter client received: " + response.message)
if __name__ == '__main__':
run()
多线程生成更新数据,迭代服务提供的最新数据简单demo,通过传入对象,对象的内部进行更新和计算的操作,对象中的方法进行更新和获取。
from concurrent import futures
import time
import grpc
import hello_pb2
import hello_pb2_grpc
import pandas as pd
import os
import threading
import time
from grpc_reflection.v1alpha import reflection
class Cal():
def __init__(self, c):
self.c = c
def cal_c(self):
self.c += 1
def get_current_c(self):
return self.c
# 实现 proto 文件中定义的 GreeterServicer
class Greeter1(hello_pb2_grpc.GreeterServicer):
def __init__(self, f):
self.f = f
# 实现 proto 文件中定义的 rpc 调用
def SayHello(self, request, context):
return hello_pb2.HelloReply(message = 'hello {msg}, {m2}'.format(msg = request.name, m2=self.f.get_current_c()))
def SayHelloAgain(self, request, context):
return hello_pb2.HelloReply(message='hello {msg}'.format(msg = request.name))
def serve():
# 启动 rpc 服务
c = Cal(0)
work = threading.Thread(target=targetf, args=(c,))
work.start()
start_server(Greeter1(c))
def start_server(grpc_server):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
server.add_insecure_port('[::]:50051')
hello_pb2_grpc.add_GreeterServicer_to_server(grpc_server, server)
service_names = "service_name"
reflection.enable_server_reflection(service_names, server)
server.start()
server.wait_for_termination()
def targetf(c):
while True:
c.cal_c()
time.sleep(2)
print(c.get_current_c())
if __name__ == '__main__':
serve()
在Cal()类中,进行累加的计算和获取当前值的计算。