gRPC 使用(python 版本)

.proto 文件

.proto 文件gRPC 和 Protocol Buffers 的接口定义文件,它描述了:

  1. 要传递什么数据(也就是消息体 message)。
  2. 要暴露什么接口(也就是服务 service 和它们的 方法)。

也就是一份规范文件,让客户端和服务端能按照相同的约定相互通信。

my_service.proto

syntax = "proto3";  // 指定使用 proto3 语法版本package demo;       // 包名,方便生成代码时分模块service MyService {// 定义 RPC 服务rpc Predict(PredictRequest) returns (PredictResponse) {}
}message PredictRequest {string prompt = 1;
}message PredictResponse {string result = 1;
}
  1. 用 protoc 自动生成客户端/服务端代码
    这里使用 python 来进行操作
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. my_service.proto
  • I. 指定 proto 搜索路径为当前目录
  • -python_out=. 生成 my_service_pb2.py(定义消息类型)
  • -grpc_python_out=. 生成 my_service_pb2_grpc.py(定义服务类接口)

因为 gRPC 要跨语言,所以必须有语言无关的描述文件

  • .proto 就是统一规范

  • Protocol Buffers 定义数据传输结构(比 JSON 轻量、高速、强类型)

  • gRPC 框架用它生成客户端/服务端、自动序列化、自动网络传输

  • protoc 会以输入文件 my_service.proto 的文件名为基准自动生成对应的 Python 文件。

  • 它没有单独的参数去自定义生成文件名,所以默认就是:

    ✅ my_service_pb2.py:

    • 包含你 .proto 中定义的 message 和 enum 类型对应的 Python 类。

    ✅ my_service_pb2_grpc.py:

    • 包含你 .proto 中定义的 service 和 RPC 方法对应的客户端和服务端桩代码。
<proto文件名>_pb2.py
<proto文件名>_pb2_grpc.py
文件包含内容用途
my_service_pb2.py消息类型类(message、enum)序列化/反序列化数据
my_service_pb2_grpc.py服务类和客户端/服务端接口实现服务逻辑/调用远程服务
  • pb2.py → 负责数据模型
  • pb2_grpc.py → 负责服务调用逻辑(RPC 接口)

服务端实现

from concurrent import futures
import grpc
import my_service_pb2
import my_service_pb2_grpc# 实现 RPC 服务
class MyService(my_service_pb2_grpc.MyServiceServicer):
# 是生成的服务端基类,这里我们继承它并实现 Predict 方法逻辑。def Predict(self, request, context):print(f"Received prompt: {request.prompt}")return my_service_pb2.PredictResponse(result=f"Hello, {request.prompt}!")# 启动 gRPC 服务器
def serve():server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))my_service_pb2_grpc.add_MyServiceServicer_to_server(MyService(), server)server.add_insecure_port("[::]:50051")server.start()print("gRPC Server running at 0.0.0.0:50051...")server.wait_for_termination()if __name__ == "__main__":serve()#  python -m grpc_tools.protoc -I. --pytheon_out=. --grpc_python_out=. my_service.proto

✅ grpc.server(…) 创建 gRPC 服务器实例,并给它分配一个线程池(能同时处理多个请求)。

✅ add_MyServiceServicer_to_server(MyService(), server) 注册我们自己实现的服务逻辑。

✅ server.add_insecure_port(“[::]:50051”) 打开监听端口。

✅ server.start() 启动服务,wait_for_termination() 让服务持续监听,不会自动结束。

_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'my_service_pb2', _globals)

  • 动态注册生成消息类

也就是:

  • PredictRequest、PredictResponse 这些类在导入时动态创建,IDE 静态分析器(比如 PyCharm)无法提前知道它们存在,因此你用 IDE 查看时找不到定义。
  • 但是程序运行时,这些类会存在,并能正常使用。
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10my_service.proto\x12\x04\x64\x65mo\" \n\x0ePredictRequest\x12\x0e\n\x06prompt\x18\x01 \x01(\t\"!\n\x0fPredictResponse\x12\x0e\n\x06result\x18\x01 \x01(\t2E\n\tMyService\x12\x38\n\x07Predict\x12\x14.demo.PredictRequest\x1a\x15.demo.PredictResponse\"\x00\x62\x06proto3')
  • AddSerializedFile(…) 把你 .proto 定义编译成的二进制描述数据注册进 DescriptorPool。
  • 也就是把整个 my_service.proto 的结构信息(服务、消息类型、字段等)塞入一个描述池中。

客户端实现

import grpc
import my_service_pb2
import my_service_pb2_grpcdef run_client():channel = grpc.insecure_channel("localhost:50051")stub = my_service_pb2_grpc.MyServiceStub(channel)response = stub.Predict(my_service_pb2.PredictRequest(prompt="World111"))print(f"Server response: {response.result}")if __name__ == "__main__":run_client()

客户端主要做三件事:

  1. 建立 gRPC 连接(channel)。
  2. 使用自动生成的 stub 来调用服务端方法。
  3. 接收服务端返回的响应并打印。
代码部分解释
grpc.insecure_channel()使用未加密通道(适合本地测试,不推荐生产环境直接用这个,要用 TLS 版 secure_channel())
MyServiceStub(channel)这是 gRPC 自动生成的客户端类,内部已经帮你实现好了 RPC 序列化、反序列化逻辑
PredictRequest()使用自动生成的类构造 RPC 请求对象,这个类对应你的 proto 中定义的消息类型
stub.Predict(…)相当于远程调用服务端的 Predict(),gRPC 会自动序列化请求、网络传输、反序列化响应
response.result服务端返回的 PredictResponse 消息对象,取它的 result 字段就是你服务返回的内容

🚀 客户端 vs 服务端对应关系

服务端:

class MyService(my_service_pb2_grpc.MyServiceServicer):def Predict(self, request, context):return my_service_pb2.PredictResponse(result=f"Hello, {request.prompt}!")

客户端:

response = stub.Predict(my_service_pb2.PredictRequest(prompt="World111")
)

客户端调用 Predict() 时:

  • 底层帮你序列化 prompt 参数并传给服务端
  • 服务端执行对应逻辑并返回 result 给客户端
  • 客户端拿到结果打印出来 🎉

也可以使用 go 来客户端,注意先

protoc --go_out=. --go-grpc_out=. my_service.proto

go

package mainimport ("context""log""time""google.golang.org/grpc"pb "path/to/generated/my_service" // 引入生成的包
)func main() {// 1️⃣ 建立 gRPC 连接conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) if err != nil {log.Fatalf("连接失败: %v", err)}defer conn.Close()// 2️⃣ 创建客户端存根client := pb.NewMyServiceClient(conn)// 3️⃣ 调用服务ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)defer cancel()resp, err := client.Predict(ctx, &pb.PredictRequest{Prompt: "Hello Go!"})if err != nil {log.Fatalf("调用错误: %v", err)}log.Printf("服务返回: %s\n", resp.Result)
}

总结

无论是 gRPC、腾讯的 tRPC,甚至国内很多 RPC 框架(例如阿里 HSF、蚂蚁 SOFA RPC),它们背后的实现思路都是一样的👇:

🔄共同点:

  1. 先定义接口协议(IDL)

    用 proto、.thrift、.proto3 或者类似 IDL 文件描述你的服务、方法、消息。

  2. 代码生成器生成对应语言的客户端/服务端存根

    protoc、trpcproto 或者对应语言插件 → 自动生成:

    • 服务接口类(Stub / Service 接口)
    • 消息类(序列化 / 反序列化逻辑)
  3. 服务端实现 Service 类逻辑

    你只需继承生成的服务接口,然后实现方法逻辑即可。

  4. 客户端用生成的存根调用方法

    就像调用本地函数一样,不需要手动拼接网络数据、序列化二进制流。

.proto 文件↓
[生成工具] 自动生成代码↓
服务端: 实现 Service 类
客户端: 使用 Client Stub 调用↓
底层负责网络传输、序列化、负载均衡、错误处理...

减少重复代码 — 不用你手写网络序列化部分

强类型检查 — 调用方/服务方都能知道数据结构

方便跨语言调用 — 一份协议,不同语言都能生成对应客户端、服务端

减少网络细节关注 — 把网络部分封装起来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/88576.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware安装

勾选【增强型键盘驱动程序】 #后期虚拟机用鼠标键盘比较好用 VMware创建主机Windows2 选择类型配置【自定义】 安装客户机操作系统【稍后安装操作系统】 客户机操作系统【Microsoft Windows】,版本选Windows最高版本 【固件类型】默认UEFI 【处理器配置】选1个处理…

【沉浸式解决问题】微服务子模块引入公共模块的依赖后无法bean未注入

目录 一、问题描述二、场景还原三、原因分析四、解决方案五、拓展知识参考文献 一、问题描述 在微服务项目中的公共模块进行了Mybatis Plus配置&#xff0c;创建了配置类并添加了Configuration注解&#xff0c;其他模块引入该模块后不生效 我这里是在Mybatis Plus公共模块中注…

SQL进阶:CASE表达式

目录 1、用一条SQL语句进行不同条件的统计 建表语句&#xff08;MySQL8&#xff09;&#xff1a; 录入数据&#xff1a; *按性别统计SQL 输出结果&#xff08;行列转换&#xff09; 2、在UPDATE语句里进行条件分支 建表语句&#xff08;MySQL8&#xff09;&#xff1a;…

哪四款AI工具让3D人物手办制作如此简单?

在当今数字化时代&#xff0c;AI技术的飞速发展为我们的生活带来了诸多便利和惊喜。其中&#xff0c;AI生成3D人物手办工具的出现&#xff0c;让我们能够轻松地将自己的创意和想象转化为实体手办&#xff0c;满足了众多手办爱好者的个性化需求。今天&#xff0c;我将为大家推荐…

Docker高级管理--Dockerfile镜像制作

目录 一:Docker 镜像管理 1:Docker 镜像结构 2:Dockerfile介绍 二:Dockerfile 语法基础 1:基础指令 2:环境设置指令 3:文件操作指令 4:执行命令指令 5:网络和暴露端口指令 6.容器挂载指令 三&#xff1a;dockerfile案例 1.构建nginx容器 一:Docker 镜像管理 Docker…

数字时代的“灵魂”之争:虚拟人形象的著作权困局与破局之道

首席数据官高鹏律师数字经济团队创作&#xff0c;AI辅助。 一、虚拟人的“数字生命”&#xff1a;一场关于“灵魂”的商业博弈 当一个虚拟偶像的“眼神”被复刻成千万个相似的数字面孔&#xff0c;当一段虚拟主播的“声音”被拆解为可交易的数据碎片——我们正在见证一个“数…

小型CI/CD搭建(TODO)

1 方案 因为是在国内&#xff0c;所以gitbub Actions&#xff0c;​​Azure DevOps​这些就直接拜拜了。 目前主流的大概是三种&#xff1a; 1 阿里云效/腾讯云CODING 2 GitLab CE GitLab Runner 3 Gitee Jenkins deepeseek比较了一下如下&#xff1a; 阿里云效 vs Git…

Android Studio flutter项目运行、打包时间太长

Android Studio&#xff1a;Android Studio Meerkat Feature Drop | 2024.3.2 Patch 1 flutter Sdk&#xff1a;3.29.3 系统&#xff1a;windows flutter sdk从2.10.5升级到3.29.3&#xff0c;但是Flutter 3.16开始新增了使用 Gradle声明式 plugins {} 块&#xff0c;gradle文…

【OpenGL学习】(六)图形添加纹理

文章目录 【OpenGL学习】&#xff08;六&#xff09;图形添加纹理纹理环绕纹理过滤纹理颜色与顶点颜色混合 OpenGL纹理介绍&#xff1a;https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/ 【OpenGL学习】&#xff08;六&#xff09;图形添加纹理 项目…

allure安装

一、安装java 需要安装java环境&#xff0c;不安装的话在运行前会报错下列问题&#xff08;前提是安装了allure未安装java&#xff09; 1.官网地址&#xff1a;https://www.oracle.com/ 2.点击”Download Java“ 3.选择JDK正式版本&#xff08;需要jdk1.8&#xff09; 4.选择W…

SpringBoot基于JavaWeb的城乡居民基本医疗信息管理系统

概述 一个基于SpringBoot框架开发的JavaWeb医疗信息管理系统&#xff0c;采用了现代化的技术架构&#xff0c;功能全面&#xff0c;非常适合作为学习项目或二次开发的基础。 主要内容 该系统主要包含以下核心功能模块&#xff1a; ​​用户管理模块​​ 实现管理员、医生、…

SQL变量声明与赋值 分支 循环

– 变量 分支 循环 – declare 变量名 数据类型 – declare 关键字&#xff0c;作用声明变量 – 变量名&#xff1a;以开头 – 数据类型&#xff1a;数据库中支持的数据类型&#xff1a;int varchar(n) text char(n) nvarchar(n) nchar(n) declare name varchar(255)– 定义多…

AWS S3 可观测性最佳实践

AWS S3 介绍 AWS S3&#xff08;Amazon Simple Storage Service&#xff09;是一种可扩展的对象存储服务&#xff0c;提供高可用性、持久性和安全性。它允许用户存储和检索任意数量的数据&#xff0c;并通过简单的 Web 服务接口访问这些数据。S3 支持多种存储类别&#xff0c;…

Ubuntu下布署mediasoup-demo

一、引言 mediasoup是一个强大的SFU架构的WebRTC流媒体服务器&#xff0c;凭借其多功能性、高性能和可扩展性&#xff0c;mediasoup成为构建多方视频会议和实时流媒体应用程序的完美选择。它具有联播、SVC、传输BWE和更多尖端功能。本文介绍了mediasoup-demo在Ubuntu下的布署。…

【JVS更新日志】物联网、智能排产APS、企业计划、规则引擎6.25更新说明!

项目介绍 JVS是企业级数字化服务构建的基础脚手架&#xff0c;主要解决企业信息化项目交付难、实施效率低、开发成本高的问题&#xff0c;采用微服务配置化的方式&#xff0c;提供了低代码数据分析物联网的核心能力产品&#xff0c;并构建了协同办公、企业常用的管理工具等&…

解决git pull,push 每次操作输入账号密码问题

服务器每次git pull 的时候都需要输入账号密码&#xff0c;一劳永逸解决它。 解决方案&#xff1a; 找到项目下 .git /config 文件&#xff0c;然后打开&#xff0c;编辑 [rootiZbp11b24d3d7nc8uvjx9mZ .git]# ls branches config description FETCH_HEAD HEAD hooks i…

Netty:深入解析AbstractByteBufAllocator架构设计

AbstractByteBufAllocator 类结构分析 类结构概览 public abstract class AbstractByteBufAllocator implements ByteBufAllocator {// 静态常量static final int DEFAULT_INITIAL_CAPACITY 256;static final int DEFAULT_MAX_CAPACITY Integer.MAX_VALUE;// ...其他常量//…

Java 日志管理与分析

为什么需要日志 ■ 发⽣了什么&#xff08;What&#xff09;。 ■ 何时发⽣的&#xff08;When&#xff09;。 ■ 发⽣于何处&#xff08;Where&#xff09;。 ■ 谁参与其中&#xff08;Who&#xff09;。 ■ 参与者来源&#xff08;第⼆个Where&#xff0c;注意与上⾯的Wher…

bmc TrueSight 监控mysql配置

bmc TrueSight 监控mysql配置 1.将pat加入mysql组 useradd pat;echo patpassword|passwd --stdin pat usermod -aG mysql pat2.设置环境变量 查看文件是否存在[rootu1acmsdp01 ~]# find / -name mysql.sock /var/lib/mysql/mysql.sock ^C [rootu1acmsdp01 ~]# cd /var/lib/my…

WinAppDriver 自动化测试:C#篇

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】