Python3 集成 gRPC 服务及 protocol buffers
- 1、gRPC是什么?
- 1.1、gRPC大致请求流程
- 1.2、gRPC特性
- 1.3、gRPC优势和劣势
- 1.3.1、优势
- 1.3.2、劣势
- 2、构建一个python3的gRPC服务
- 2.1、虚拟环境搭建(可选择自动安装pip)
- 2.1、引入相关依赖
- 2.2、创建项目
- 2.2.1、项目整体结构
- 2.3、编写proto
- 2.4、将example.proto文件编译成python文件
- 2.5、 执行后将在~/grpc_example/proto文件下新增3个文件
- 2.6、 编写服务端
- 2.7、编写客户端
- 2.8、启动服务端
- 2.9、启动客户端
- 3、运行效果展示
- 3.1、服务端效果
- 3.2、客户端效果
- 4、gRPC官网地址
1、gRPC是什么?
-
在说gRPC之前,我们先说REST通信。当前在设计软件产品的时候,开发人员可能接触的更多的是基于REST的通信。REST通信是非常灵活的一种方式,将资源发布在网络,由客户端通过http或者http2协议与资源进行交互,现在的微服务基本上都是运用这种技术框架。而RPC是和REST不同的一种通信架构。
-
RPC 最终的效果是让开发人员的可以像调用本地方法一样调用远程服务提供的方法。gRPC是RPC的一种,目前许多公司按照自己的需求和需要设计了自己的RPC通信架构,gRPC就是由谷歌研发的一个RPC通信框架。g代表global全球化的意思。它是一种高性能、支持多种开发语言的通信架构。
1.1、gRPC大致请求流程
1、客户端(gRPC client)调用方法,发起RPC调用
2、对请求信息使用 Protobuf 进行对象序列化。
3、服务端(gRPC Server)接收到请求后,反序列化请求信息,进行业务逻辑处理并返回。
4、对响应结果使用 Protobuf 进行对象序列化。
5、客户端接受到服务端响应,反序列化返回的信息。回调被调用的 A 方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果。
1.2、gRPC特性
-
grpc可以跨语言使用。支持多种语言 支持C++、Java、Go、Python、Ruby、C#、Node.js、Android Java、Objective-C、PHP等编程语言
-
基于 IDL ( 接口定义语言(Interface Define Language))文件定义服务,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端Stub;
-
通信协议基于标准的 HTTP/2 设计,支持·双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量;
-
序列化支持 PB(Protocol Buffer)和 JSON,PB 是一种语言无关的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 调用的高性能。
-
安装简单,扩展方便(用该框架每秒可达到百万个RPC)
1.3、gRPC优势和劣势
1.3.1、优势
- Protobuf序列化和反序列化的速度,是JSON的5倍。
- gRPC是为HTTP/2而设计的,它是HTTP的一个主要版本,与HTTP 1.x相比具有显著的性能优势:二进制框架和压缩。HTTP/2协议在发送和接收方面都很紧凑和高效。通过单个TCP连接复用多个HTTP/2调用。多路复用消除了线头阻塞。
1.3.2、劣势
-
浏览器支持有限,
-
当下,不可能直接从浏览器调用gRPC服务。gRPC大量使用HTTP/2功能,没有浏览器提供支持gRPC客户机的Web请求所需的控制级别。gRPC Web并非支持所有gRPC功能。不支持客户端和双向流,并且对服务器流的支持有限。
-
不是人类可读的
-
HTTP API请求以文本形式发送,可以由人读取和创建。
-
但它的二进制格式是不可读的。
2、构建一个python3的gRPC服务
步骤:
- 引入相关依赖
- 编写protobuf
- 将protobuf转成python代码
- 开发gRPC服务
2.1、虚拟环境搭建(可选择自动安装pip)
- 创建虚拟环境
- 自动安装pip执行命令:
python3 -m venv myenv- 手动pip执行命令:
python3 -m venv --without-pip myenv
- 启动虚拟环境
source /xxx/xxx/myenv/bin/activate
- 手动安装pip
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
sudo python3 get-pip.py
2.1、引入相关依赖
通过pip3安装对应的包
pip3 install grpcio-tools -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip3 install grpcio -i https://pypi.tuna.tsinghua.edu.cn/simple/
2.2、创建项目
mkdir -P ~/grpc_example/{proto,client,server}
2.2.1、项目整体结构
2.3、编写proto
vim ~/grpc_example/proto/example.proto
syntax = "proto3";package your_package_name;message YourRequest {string name = 1;
}message YourResponse {string message = 1;
}service YourService {rpc YourRPCMethod (YourRequest) returns (YourResponse);
}
2.4、将example.proto文件编译成python文件
python3 -m grpc_tools.protoc -I ./proto --python_out=./proto --pyi_out=./proto --grpc_python_out=./proto proto/example.proto
2.5、 执行后将在~/grpc_example/proto文件下新增3个文件
example_pb2.py
example_pb2_grpc.py
example_pb2.pyi
2.6、 编写服务端
vim ~/grpc_example/client/client.py
# -*- coding:utf-8 -*-
import sys
import pathlibabspathfile = pathlib.Path(__file__)
package_path = abspathfile.absolute().parent.parent.parent
sys.path.append(str(package_path))import grpc
from concurrent import futures
from example.proto import example_pb2
from example.proto import example_pb2_grpcclass YourService(example_pb2_grpc.YourServiceServicer):def YourRPCMethod(self, request, context):name = request.name# 实现自己的RPC方法逻辑response = example_pb2.YourResponse()response.message = "Hello, " + nameprint("response", response)return responsedef serve():server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))example_pb2_grpc.add_YourServiceServicer_to_server(YourService(), server)server.add_insecure_port("[::]:50051")print("开启服务")server.start()server.wait_for_termination()if __name__ == '__main__':serve()
2.7、编写客户端
vim ~/grpc_example/server/server.py
# -*- coding:utf-8 -*-
import sys
import pathlibabspathfile = pathlib.Path(__file__)
package_path = abspathfile.absolute().parent.parent.parent
sys.path.append(str(package_path))import grpc
from example.proto import example_pb2
from example.proto import example_pb2_grpcdef run():channel = grpc.insecure_channel("localhost:50051")stub = example_pb2_grpc.YourServiceStub(channel)request = example_pb2.YourRequest()request.name = "zsc"# 设置请求参数response = stub.YourRPCMethod(request)print("response", response)if __name__ == '__main__':run()
2.8、启动服务端
python3 ~/grpc_example/server/server.py
2.9、启动客户端
python3 ~/grpc_example/client/client.py
3、运行效果展示
3.1、服务端效果
3.2、客户端效果
4、gRPC官网地址
-
gRpc官网地址:https://www.grpc.io
-
gRpc中文文档地址:http://doc.oschina.net/grpc