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

在这里插入图片描述

2.2 解压缩、配置文件

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

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

2.2.3 终端输入命令

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

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

在这里插入图片描述

2.3 验证是否安装成功

protoc --version

在这里插入图片描述

三、简单实例

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 文件

在这里插入图片描述

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 输出结果:

在这里插入图片描述

四、服务端客户端实例

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

目录结构如下:

在这里插入图片描述

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 输出结果

在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐