zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【Python分布式服务框架】python实现gRPC服务

Python服务框架 实现 grpc 分布式服务
2023-09-11 14:19:33 时间


gRPC服务

1. 为什么选择 gRPC?

gRPC 是一个现代开源的高性能远程过程调用 (RPC) 框架,可以在任何环境中运行。它可以通过对负载平衡、跟踪、健康检查和身份验证的可插拔支持有效地连接数据中心内和跨数据中心的服务。它也适用于分布式计算的最后一英里,将设备、移动应用程序和浏览器连接到后端服务。

简单的服务定义

使用强大的二进制序列化工具集和语言 Protocol Buffers 定义您的服务。

快速启动并扩展

只需一行即可安装运行时和开发环境,还可以使用该框架扩展到每秒数百万个 RPC 。

跨语言和平台工作

以各种语言和平台为您的服务自动生成惯用的客户端和服务器存根。

双向流和集成身份验证

双向流式传输和完全集成的可插拔身份验证以及基于 HTTP/2 的传输。

2. Python gRPC

2.1. 安装 gRPC 环境

Python 的 gRPC 基础库

pip install grpcio

Python 的 gRPC 工具包括协议缓冲区编译器protoc和用于从.proto服务定义生成服务器和客户端代码的特殊插件。

pip install grpcio-tools

2.2. gRPC 服务端示例

# coding=gbk
import asyncio
from grpc.experimental import aio
from concurrent import futures  # 多线程包


async def start_server():
    # start rpc service
    server = aio.server(
        futures.ThreadPoolExecutor(max_workers=4),
        options=[
            ('grpc.so_reuseport', 0),
            ('grpc.max_send_message_length', 100 * 1024 * 1024),
            ('grpc.max_receive_message_length', 100 * 1024 * 1024),
            ('grpc.enable_retries', 1),
            ('grpc.keepalive_permit_without_calls', 0),
            ('grpc.keepalive_timeout_ms', 5000),
            ('grpc.keepalive_time_ms', 10000),
        ]
    )
    
    # 需要服务
    
    server.add_insecure_port(f'[::]:8000')

    # 加入服务
    await server.start()

    # since server.start() will not block,
    # a sleep-loop is added to keep alive
    try:
        await server.wait_for_termination()
    except KeyboardInterrupt:
        await server.stop(None)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([start_server()]))
    loop.close()

2.3. gRPC 客户端示例

# coding=gbk
import grpc

channel = grpc.insecure_channel('localhost:8000')

3. 注册服务

3.1. Protobuf

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

3.2. 一个简单的

这里我们需要掌握服务的定义方式。

// 定义proto版本
syntax = "proto3";

// 包名称
package greeter;

// 定义服务
service Greeter {
  // 定义方法
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 定义数据结构
message HelloRequest {
  string name = 1;
}

// 定义数据结构
message HelloReply {
  string message = 1;
}

3.3. proto3常用数据类型

  • float:浮点型,对应python中的float,默认值0
  • int32:整型,对应python中的int,默认值0
  • int64:长整型,对应python中的long,默认值0
  • bool:布尔型,对应python中的bool,默认值false
  • string:字符型,对应python中的str,默认值""
  • 注:因为默认值的存在,对请求参数和响应值有影响,会有非预期的情况产生,这个我们后面讨论。

3.4. 实现服务功能逻辑

安装Python依赖库

pip install google-api-python-client==2.9.0

生成协议对应的Python代码

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

执行上面的命令,在当前目录会产生两个文件,分别是greeter_pb2.py和greeter_pb2_grpc.py。
greeter_pb2.py:中定义的是服务所需的数据结构;
greeter_pb2_grpc.py:中定义的 客户端类、服务端类和服务注册方法。

# coding=gbk
import greeter_pb2, greeter_pb2_grpc


class Greeter(greeter_pb2_grpc.GreeterServicer):

    async def SayHello(self, request, context):
        return greeter_pb2.HelloReply(message=f"Hello {request.name}")

服务端

from greeter_pb2_grpc import add_GreeterServicer_to_server
from service import Greeter

...

    )

    add_GreeterServicer_to_server(servicer=Greeter(), server=server)

    server.add_insecure_port(f'[::]:8000')

客户端

# coding=gbk
import grpc
from greeter_pb2_grpc import GreeterStub
from greeter_pb2 import HelloRequest

channel = grpc.insecure_channel('localhost:8000')
sub = GreeterStub(channel=channel)
ret = sub.SayHello(HelloRequest(name="不太灵光的程序员"))
print(ret.message)

启动服务

python server.py

python client.py

在这里插入图片描述