grpc的通信模式有4种,分别是
单次请求——单次回应
单次请求——流式回应
流式请求——单次回应
双向流
放在这里是为了以后自己再用的时候能快速拿起来用
展示一下demo吧
proto
syntax = "proto3";
// 定义一个服务
service ReturnBytes
{
// 双向流
rpc RetBytes (stream Req) returns (stream Resp);
// 单次请求返回流
rpc RetBytesWithoutStream (Req) returns (Resp);
// 请求流对单次返回
rpc OneToStream (Req) returns (stream Resp);
// 单次请求单次返回
rpc StreamToOne (stream Req) returns (Resp);
}
message Req
{
string query = 1;
}
message Resp {
bytes res = 1;
}
下面是服务端的代码
from concurrent import futures
import grpc
import contact_pb2
import contact_pb2_grpc
class ReturnBytes(contact_pb2_grpc.ReturnBytesServicer):
"""
测试grpc的通信模式,对消息只做字符串和二进制的格式修改
"""
def RetBytes(self, request_iterator, context):
for req in request_iterator:
s = req.query
b = s.encode('utf-8')
yield contact_pb2.Resp(res=b)
def RetBytesWithoutStream(self, request, context):
s = request.query
b = s.encode('utf-8')
return contact_pb2.Resp(res=b)
def OneToStream(self, request, context):
s = request.query
for i in range(10):
yield contact_pb2.Resp(res=f'{s}-{i}'.encode('utf8'))
def StreamToOne(self, request_iterator, context):
msg_count = 0
for req in request_iterator:
print(req.query)
msg_count += 1
return contact_pb2.Resp(
res=f'received {msg_count} msgs'.encode('utf8'))
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
contact_pb2_grpc.add_ReturnBytesServicer_to_server(
ReturnBytes(), server)
server.add_insecure_port("[::]:50051")
server.start()
print("grpc server start...")
server.wait_for_termination()
if __name__ == '__main__':
serve()
下面是客户端代码
from pprint import pprint
import grpc
import contact_pb2
import contact_pb2_grpc
def two_way_flow(queries):
with grpc.insecure_channel('localhost:50051') as channel:
stub = contact_pb2_grpc.ReturnBytesStub(channel=channel)
"""
这里两层括号是为了明确这个地方传的是个生成器
等同于
def gen(queries):
for i in queries:
yield contact_pb2.Req(query=str(i)
"""
resp = stub.RetBytes(
(contact_pb2.Req(query=str(i)) for i in queries)
)
for i in resp:
yield i
def one_to_stream():
with grpc.insecure_channel('localhost:50051') as channel:
stub = contact_pb2_grpc.ReturnBytesStub(channel=channel)
resp = stub.OneToStream(contact_pb2.Req(query='test_one_to_stream'))
for r in resp:
print(r.res)
def stream_to_one():
with grpc.insecure_channel('localhost:50051') as channel:
stub = contact_pb2_grpc.ReturnBytesStub(channel=channel)
"""
这里两层括号是为了明确这个地方传的是个生成器
等同于
def gen(queries):
for i in range(10):
yield contact_pb2.Req(query=str(i)
"""
resp = stub.StreamToOne(
(contact_pb2.Req(query=str(i)) for i in range(10))
)
print(resp.res)
def one_to_one():
with grpc.insecure_channel('localhost:50051') as channel:
stub = contact_pb2_grpc.ReturnBytesStub(channel=channel)
resp = stub.RetBytesWithoutStream(
contact_pb2.Req(query='test_one_to_one'))
print(resp.res)
if __name__ == '__main__':
g = two_way_flow([f'test_stream_2_stream_{n}' for n in range(10)])
pprint([msg.res for msg in g])
print('-=' * 20)
one_to_stream()
print('-=' * 20)
stream_to_one()
print('-=' * 20)
one_to_one()