简介:谈一谈tcp,http,socket,rpc,grpc
前置条件:
Python版本3.5+
pip版本9.0.1+
安装 gRPC:
python -m pip install grpcio
protobuf:grpc 使用 protobuf 进行数据传输,protobuf 是一种数据交换格式, 由三部分组成:
proto文件
protoc
protobuf 运行时所需要的库
名词解释:
1、proto 文件: 使用的 proto 语法的文本文件, 用来定义数据格式
2、protoc: protobuf 编译器(compile), 将 proto 文件编译成不同语言的实现, 这样不同语言中的数据就可以和 protobuf 格式的数据进行交互
3、protobuf 运行时(runtime): protobuf 运行时所需要的库, 和 protoc 编译生成的代码进行交互
proto语法现在有 proto2 和 proto3 两个版本, 推荐使用 proto3。
使用 protobuf 的过程:
1、编写 proto 文件
2、使用 protoc 编译
3、添加 protobuf 运行时
4、项目中集成
更新 protobuf 的过程:
1、修改 proto 文件
2、使用 protoc 重新编译
3、项目中修改集成的地方
创建proto文件:
syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
gRPC 工具:Python 的 gRPC 工具包括协议缓冲区编译器和用于从服务定义protoc生成服务器和客户端代码的特殊插件。
安装 gRPC 工具:
python -m pip install grpcio-tools
使用 protoc 编译 proto 文件, 生成 python 语言的实现
python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. helloworld.proto
参数解析:
python -m grpc_tools.protoc: python 下的 protoc 编译器通过 python 模块(module) 实现,
--python_out=. : 编译生成处理 protobuf 相关的代码的路径, 这里生成到当前目录
--grpc_python_out=. : 编译生成处理 grpc 相关的代码的路径, 这里生成到当前目录
-I. helloworld.proto : proto 文件的路径, 这里的 proto 文件在当前目录
编译后生成的代码:
helloworld_pb2.py: 用来和 protobuf 数据进行交互
helloworld_pb2_grpc.py: 用来和 grpc 进行交互
编写 helloworld 的 grpc 实现:服务器端helloworld_grpc_server.py
# -*- coding: utf-8 -*-
from concurrent import futures
import time
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
# 实现 proto 文件中定义的 GreeterServicer
class Greeter(helloworld_pb2_grpc.GreeterServicer):
# 实现 proto 文件中定义的 rpc 调用
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='hi {msg}'.format(msg=request.name))
def SayHelloAgain(self, request, context):
return helloworld_pb2.HelloReply(message='hello {msg}'.format(msg=request.name))
def serve():
# 启动 rpc 服务
print("启动 rpc helloworld 服务")
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_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()
客户端: helloworld_grpc_client.py
# -*- coding: utf-8 -*-
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
# 连接 rpc 服务器
channel = grpc.insecure_channel('localhost:50051')
# 调用 rpc 服务
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='python'))
print("Greeter client received: " + response.message)
response = stub.SayHelloAgain(helloworld_pb2.HelloRequest(name='grpc'))
print("Greeter client received: " + response.message)
if __name__ == '__main__':
run()
运行 python helloworld_grpc_server.py
运行 python helloworld_grpc_client.py
知识扩展:
grpc basic: 4 种通信方式
helloworld 使用了最简单的 grpc 通信方式: 类似 http 协议的一次 request+response。
根据不同的业务场景, grpc 支持 4 种通信方式:
客服端一次请求, 服务器一次应答
客服端一次请求, 服务器多次应答(流式)
客服端多次请求(流式), 服务器一次应答
客服端多次请求(流式), 服务器多次应答(流式)
官方提供了一个 route guide service 的 demo, 应用到了这 4 种通信方式, 具体的业务如下:
数据源: json 格式的数据源, 存储了很多地点, 每个地点由经纬度(point)和地名(location)组成
通信方式 1: 客户端请求一个地点是否在数据源中
通信方式 2: 客户端指定一个矩形范围(矩形的对角点坐标), 服务器返回这个范围内的地点信息
通信方式 3: 客户端给服务器发送多个地点信息, 服务器返回汇总信息(summary)
通信方式 4: 客户端和服务器使用地点信息 聊天(chat)
微信公众号:玩转测试开发
欢迎关注,共同进步,谢谢!