Python 实现 gRPC 与 原始 RPC 的对比:理解 RPC 的基本功能

news/2025/2/11 1:56:12/

在分布式系统中,远程过程调用(Remote Procedure Call,RPC) 是一项关键技术,它允许不同计算机之间像调用本地函数一样进行通信。本文通过 Python 代码对比 gRPC 和 原始 RPC(基于 Socket) 来分析 RPC 的基本功能。


1. 什么是 RPC?

RPC(Remote Procedure Call) 是一种允许程序在 不同的进程、机器 之间像调用本地函数一样执行远程函数的技术。本地进程(客户端)调用远程服务器上的方法,服务器执行方法后将结果返回给客户端。

RPC 的核心功能

  1. 客户端-服务器通信:通过网络请求调用远程方法
  2. 序列化与反序列化:将数据转换成可传输格式(JSON、Protobuf)
  3. 自动化传输:隐藏底层通信逻辑,让调用方式更直观
  4. 错误处理:支持异常返回

2. gRPC 与 原始 RPC(基于 Socket) 对比

功能gRPC原始 RPC(Socket)
序列化Protobuf(二进制,高效)JSON(文本格式,易读但体积大)
传输协议HTTP/2(高性能)纯 TCP(需手写协议)
代码生成支持 .proto 自动生成需手写所有请求/响应逻辑
流式通信支持(客户端流、服务器流、双向流)需要手动实现
多语言支持Python、Go、Java 等仅限 Python(除非自行实现跨语言支持)
安全性内置 TLS/SSL 支持需手动加密
性能高效、低延迟较低(TCP+JSON 开销大)

接下来,我们分别实现 gRPC 和 原始 RPC 进行对比。


3. gRPC 实现

gRPC 使用 Protobuf 进行序列化,并自动生成 客户端和服务器端代码

3.1 定义 gRPC 服务

创建 rpc_service.proto

syntax = "proto3";package rpcdemo;service MathService {rpc Add (AddRequest) returns (AddResponse);
}message AddRequest {int32 a = 1;int32 b = 2;
}message AddResponse {int32 result = 1;
}

生成 Python 代码:

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

3.2 gRPC 服务器

python">import grpc
from concurrent import futures
import rpc_service_pb2
import rpc_service_pb2_grpcclass MathService(rpc_service_pb2_grpc.MathServiceServicer):def Add(self, request, context):return rpc_service_pb2.AddResponse(result=request.a + request.b)def serve():server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))rpc_service_pb2_grpc.add_MathServiceServicer_to_server(MathService(), server)server.add_insecure_port('[::]:50051')server.start()print("gRPC Server started on port 50051")server.wait_for_termination()if __name__ == "__main__":serve()

3.3 gRPC 客户端

python">import grpc
import rpc_service_pb2
import rpc_service_pb2_grpcdef run():channel = grpc.insecure_channel('localhost:50051')stub = rpc_service_pb2_grpc.MathServiceStub(channel)response = stub.Add(rpc_service_pb2.AddRequest(a=10, b=20))print("gRPC Response:", response.result)if __name__ == "__main__":run()

4. 原始 RPC(Socket 实现)

使用 Python 原生 socket 来模拟 RPC 机制。

4.1 原始 RPC 服务器

python">import socket
import json# 定义计算服务
def add(a, b):return a + b# 注册可调用的函数
FUNCTIONS = {"add": add
}def handle_client_connection(client_socket):""" 处理客户端请求 """try:# 接收数据data = client_socket.recv(1024).decode('utf-8')request = json.loads(data)# 获取方法名和参数method = request.get("method")params = request.get("params", [])# 执行方法if method in FUNCTIONS:result = FUNCTIONS[method](*params)response = {"status": "success", "result": result}else:response = {"status": "error", "message": "Method not found"}# 发送响应client_socket.send(json.dumps(response).encode('utf-8'))except Exception as e:response = {"status": "error", "message": str(e)}client_socket.send(json.dumps(response).encode('utf-8'))finally:client_socket.close()def start_server(host='localhost', port=5000):""" 启动RPC服务器 """server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server.bind((host, port))server.listen(5)print(f"RPC Server listening on {host}:{port}")while True:client_sock, _ = server.accept()handle_client_connection(client_sock)if __name__ == "__main__":start_server()

4.2 原始 RPC 客户端

python">import socket
import jsondef rpc_call(method, params, host='localhost', port=5000):""" 发送 RPC 请求 """client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect((host, port))# 构造请求数据request = json.dumps({"method": method,"params": params})# 发送数据client.send(request.encode('utf-8'))# 接收响应response_data = client.recv(1024).decode('utf-8')response = json.loads(response_data)client.close()return responseif __name__ == "__main__":result = rpc_call("add", [10, 20])print("RPC Response:", result)

5. 总结

5.1 gRPC 与 原始 RPC 的区别

特性gRPC原始 RPC(Socket)
序列化方式Protobuf(高效二进制)JSON(文本格式)
传输协议HTTP/2TCP
自动代码生成支持(通过 .proto不支持(需手动实现)
流式传输支持(双向流、流式响应)需要手动实现
多语言支持支持多种语言(Python、Go、Java 等)仅支持 Python
性能高效,低延迟相对较慢(TCP+JSON 有额外开销)

5.2 选择哪种 RPC?

gRPC 适用于:

  • 分布式系统(微服务架构)
  • 多语言通信(前端、后端不同语言)
  • 高性能数据传输(Protobuf + HTTP/2)

原始 RPC(Socket) 适用于:

  • 小型应用(轻量级进程间通信)
  • 学习 RPC 原理
  • 内部服务(单机内进程间通信)

若有错误与不足请指出,关注DPT一起进步吧!!!


http://www.ppmy.cn/news/1571020.html

相关文章

Spring Boot Actuator使用

说明&#xff1a;本文介绍Spring Boot Actuator的使用&#xff0c;关于Spring Boot Actuator介绍&#xff0c;下面这篇博客写得很好&#xff0c;珠玉在前&#xff0c;我就不多介绍了。 Spring Boot Actuator 简单使用 项目里引入下面这个依赖 <!--Spring Boot Actuator依…

【STM32】串口原理

单片机有自己的RX&#xff08;接收端&#xff09;&#xff0c;TX&#xff08;发送端&#xff09;&#xff0c;有的需要再共同接一个底线&#xff0c;为了保证有相同的参考电势&#xff0c;数据如果是高电平的话&#xff0c;发送过去也是高电平 1.轮询方式 CPU需要时刻注意发送…

deepseek笔记

文章目录 deepseek 手机appdeepseek apideepseek的底层原理?个人感悟 deepseek 字面意思是深度求索&#xff0c;看这个名字就和人工智能有关。 百度了下 公司名称叫做 杭州深度求索人工智能基础技术研究有限公司。 deepseek 手机app 抱着好奇的心理&#xff0c;下载了一个&am…

YOLOv11实时目标检测 | 摄像头视频图片文件检测

在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492&#xff0c;我们详细探讨了YOLO11的部署以及推理训练&#xff0c;但是评论区的观众老爷就说了&#xff1a;“博主博主&#xff0c;你这个只能推理…

软件工程与土木工程的不同

观看本视频后&#xff0c;你将能够认识到软件工程与土木工程的不同&#xff0c;描述软件工程是如何不断变化的&#xff0c;并阐述项目管理模式为何不太适用于软件开发。一种常见且不利于 DevOps 工作的做法是&#xff0c;把软件工程工作当作土木工程来做。 对于一个土木工程的项…

Lua中文语言编程源码-第十一节,其它小改动汉化过程

__tostring 汉化过程 liolib.c metameth[] {"__转换为字符串", f_tostring}, lauxlib.c luaL_callmeta(L, idx, "__转换为字符串") lua.c luaL_callmeta(L, 1, "__转换为字符串") __len 汉化过程 ltm.c luaT_eventname[] ltablib.c c…

我用AI做数据分析之数据清洗

我用AI做数据分析之数据清洗 AI与数据分析的融合效果怎样&#xff1f; 这里描述自己在使用AI进行数据分析&#xff08;数据清洗&#xff09;过程中的几个小故事&#xff1a; 1. 变量名的翻译 有一个项目是某医生自己收集的数据&#xff0c;变量名使用的是中文&#xff0c;分…

初识C语言、C语言的学习方向总述与入门

目录 1. 什么是C语言&#xff1f; 2. 第一个C语言程序 3. 数据类型 4. 变量、常量 4.1 定义变量的方法 4.2 变量的命名 4.3 变量的分类 4.4 变量的作用域和生命周期 4.5 常量 5. 字符串转义字符注释 5.1 字符串 5.2 转义字符 6. 注释 7. 选择语句 8. 循环语句 …