文章目录

  • python-gRPC
  • 一、简介
  • 1.1 gRPC
  • 1.2 protobuf
  • 二、windows 环境下安装protobuf
  • 2.1 下载环境包
  • 2.2 解压缩、配置文件
  • 2.3 验证是否安装成功
  • 三、简单实例
  • 3.1新建包
  • 3.2 新建proto文件
  • 3.3 终端使用protoc编译生成proto文件
  • 3.4 编写测试代码
  • 3.5 输出结果:
  • 四、服务端客户端实例
  • 4.1 安装依赖包
  • 4.2 新建data.proto文件
  • 4.3 生成proto数据的python调用格式,gRPC方法接口
  • 4.4 gRPC服务端
  • 4.5 gRPC客户端
  • 4.6 输出结果


python-gRPC

一、简介

1.1 gRPC

服务和服务之间调用需要使用RPC,gRPC是一款语言中立、平台中立、开源的远程过程调用系统,gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用。

数据在进行网络传输的时候,需要进行序列化,序列化协议有很多种,比如xml, json,protobuf等。gRPC默认使用protocol buffers,这是google开源的一套成熟的结构数据序列化机制。

序列化:将数据结构或对象转换成二进制串的过程。
反序列化:将在序列化过程中所产生的二进制串转换成数据结构或对象的过程。

1.2 protobuf

protobuf是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。

优势:

  1. 序列化后体积相比Json和XML很小,适合网络传输
  2. 支持跨平台多语言
  3. 消息格式升级和兼容性还不错
  4. 序列化反序列化速度很快

二、windows 环境下安装protobuf

2.1 下载环境包

https://github.com/protocolbuffers/protobuf/releases

python grpc 配置log_python grpc 配置log

2.2 解压缩、配置文件

2.2.1 把protoc-22.4-win64文件夹下面的protoc.exe移至protobuf-python-22.4/src目录下

python grpc 配置log_序列化_02

python grpc 配置log_python grpc 配置log_03

2.2.2 在protobuf-python-22.4.1/python目录下进入cmd界面

python grpc 配置log_python grpc 配置log_04

2.2.3 终端输入命令

python setup.py build
python setup.py test
python setup.py install

2.2.4 把protoc.exe所在的目录添加至环境变量(下图这个目录)

python grpc 配置log_python_05

2.3 验证是否安装成功

protoc --version

python grpc 配置log_python grpc 配置log_06

三、简单实例

3.1新建包

在Pycharm中新建一个package 叫做protobufExample

3.2 新建proto文件

在protobufExample下面新建一个proto文件,取名person

syntax = "proto3";
package protobufExample;

message person {
    int32 id = 1;
    string name = 2;
}

message all_person {
    repeated person Per = 1;
}

3.3 终端使用protoc编译生成proto文件

如图:

$ protoc --python_out=. person.proto 
#生成 person.pb2.py 文件

python grpc 配置log_序列化_07

3.4 编写测试代码

main.py中编写序列化与反序列化的测试代码:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from protobufExample import person_pb2
 
# 为 all_person 填充数据
pers = person_pb2.all_person()
p1 = pers.Per.add()
p1.id = 1
p1.name = 'xieyanke'
p2 = pers.Per.add()
p2.id = 2
p2.name = 'pythoner'
 
# 对数据进行序列化
data = pers.SerializeToString()
 
# 对已经序列化的数据进行反序列化
target = person_pb2.all_person()
target.ParseFromString(data)
print(target.Per[1].name)  #  打印第一个 person name 的值进行反序列化验证
print(target.Per[1].id)

3.5 输出结果:

python grpc 配置log_序列化_08

四、服务端客户端实例

使用案例:小写字符串转换为大写字符串

目录结构如下:

python grpc 配置log_服务端_09

4.1 安装依赖包

pip install protobuf
pip install grpcio
pip install grpcio-tools

4.2 新建data.proto文件

data.proto 为protobuf格式文件,定义了数据类以及远程调用方法。

syntax = "proto3";
package base_package;


service FormatData {   //定义服务,用在rpc传输中
  rpc DoFormat(actionrequest) returns (actionresponse){}
}

message actionrequest {
  string text = 1;
}

message actionresponse{
  string text=1;
}

4.3 生成proto数据的python调用格式,gRPC方法接口

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. data.proto

生成 data_pb2.py 和 data_pb2_grpc.py,其中 data_pb2.py 为数据格式文件,data_pb2_grpc.py 为gRPC方法文件。

4.4 gRPC服务端

服务端具体实现了proto文件中定义的方法 DoFormat,将实现后的服务类添加到gRPC服务端中,当服务端接收到客户端要调用的函数名时通过反射机制执行具体的方法并返回执行结果。

import grpc
import time
from concurrent import futures
from gRPC import data_pb2, data_pb2_grpc

_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_HOST = 'localhost'
_PORT = '8080'


class FormatData(data_pb2_grpc.FormatDataServicer):
    # 重写接口函数
    def DoFormat(self, request, context):
        str = request.text
        return data_pb2.actionresponse(text=str.upper())  # 返回一个类实例


def server():
    # 定义服务器并设置最大连接数,corcurrent.futures是一个并发库,类似于线程池的概念
    grpcServer = grpc.server(futures.ThreadPoolExecutor(max_workers=4))  # 创建一个服务器
    data_pb2_grpc.add_FormatDataServicer_to_server(FormatData(), grpcServer)  # 在服务器中添加派生的接口服务(自己实现了处理函数)
    grpcServer.add_insecure_port(_HOST + ':' + _PORT)  # 添加监听端口
    grpcServer.start()  # 启动服务器
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        grpcServer.stop(0)  # 关闭服务器


if __name__ == '__main__':
    server()

4.5 gRPC客户端

客户端连接gRPC服务端后,即可进行远程过程调用。

import grpc
from gRPC import data_pb2, data_pb2_grpc

_HOST = 'localhost'
_PORT = '8080'


def run():
    conn = grpc.insecure_channel(_HOST + ':' + _PORT)  # 监听频道
    client = data_pb2_grpc.FormatDataStub(channel=conn)  # 客户端使用Stub类发送请求,参数为频道,为了绑定链接
    response = client.DoFormat(data_pb2.actionrequest(text='hello,world!'))  # 返回的结果就是proto中定义的类
    print("received: " + response.text)


if __name__ == '__main__':
    run()

4.6 输出结果

python grpc 配置log_python_10