【知识】RPC和gRPC
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn]
如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~
RPC
1. RPC 的定义
RPC(Remote Procedure Call,远程过程调用) 是一种进程间通信协议。它允许程序调用另一台机器(或同一台机器的其他进程)上的函数/过程,好像在调用本地函数一样,隐藏了网络通信的细节。
核心思想:
-
调用者像调用本地函数一样调用远程函数。
-
底层通过序列化(编码)请求、网络传输、远程解码执行,再将结果返回。
2. RPC 的基本流程
-
客户端调用本地代理(Stub)方法。
-
Stub 将方法名、参数等序列化(通常称为 封送/marshalling)。
-
序列化后的数据通过网络发送到服务端。
-
服务端收到后,反序列化(解封装),调用真正的服务函数。
-
服务函数执行完,将结果序列化,通过网络返回。
-
客户端 Stub 收到后反序列化,返回结果。
👉 即:
Client -> stub -> network -> server -> real function -> return
3. RPC 的优点
-
把远程调用封装得像本地函数调用一样,降低了分布式编程的复杂度。
-
可以跨语言、跨平台。
-
能在微服务架构中实现服务间解耦。
4. 实现示例
这是使用 socket
+ pickle
来模拟最原始的 RPC,帮助理解核心原理。
服务端(Server)
# server.py
import socket
import pickledef add(x, y):return x + ydef handle_request(data):func_name, args = pickle.loads(data)if func_name == 'add':return pickle.dumps(add(*args))return pickle.dumps("Unknown function")server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 8000))
server.listen(5)
print("RPC Server running on port 8000...")while True:client, addr = server.accept()data = client.recv(1024)result = handle_request(data)client.send(result)client.close()
客户端(Client)
# client.py
import socket
import pickledef remote_call(func_name, args):client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(('localhost', 8000))client.send(pickle.dumps((func_name, args)))data = client.recv(1024)client.close()return pickle.loads(data)print("Calling remote add(5, 7)...")
result = remote_call('add', (5, 7))
print("Result:", result)
启动方式
python server.py
# 另开终端
python client.py
输出结果
Calling remote add(5, 7)...
Result: 12
gRPC
1. gRPC 的定义
gRPC 是 Google 开源的高性能、通用的 RPC 框架,用来在分布式系统中进行服务间通信。它基于:
-
HTTP/2(高效双向流传输,支持多路复用、头部压缩、流控)
-
Protocol Buffers(protobuf)(高效序列化)
2. gRPC 的特点
- 多语言支持:官方支持 Go、Java、C++、Python、C#、Node.js、PHP、Ruby 等。
- IDL(接口定义语言)统一规范:用
.proto
文件定义服务接口和消息结构。自动生成客户端 & 服务端代码。 - 高效序列化:使用 protobuf,比 JSON / XML 更紧凑、更快。
- 基于 HTTP/2:
-
支持多路复用(一个 TCP 连接上多条流),减少连接数量
-
头部压缩减少带宽
-
支持流式数据(Client Streaming、Server Streaming、Bi-directional Streaming)
-
- 内置健康检查、超时、重试、负载均衡、认证
3. gRPC 的工作原理
-
使用
.proto
文件定义服务和消息。 -
通过
protoc
生成客户端 & 服务端代码。 -
客户端通过生成的 Stub 调用服务端,就像调用本地方法。
4. 使用示例
下面是一个标准的 gRPC 示例,用 .proto
文件定义接口,然后生成 Python 代码并运行。
定义 proto 文件:新建 helloworld.proto
syntax = "proto3";package helloworld;service Greeter {rpc SayHello (HelloRequest) returns (HelloReply);
}message HelloRequest {string name = 1;
}message HelloReply {string message = 1;
}
生成 Python 代码
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
会生成:
helloworld_pb2.py
(消息类)
helloworld_pb2_grpc.py
(服务类)
实现服务端:新建 server.py
from concurrent import futures
import grpc
import helloworld_pb2
import helloworld_pb2_grpcclass Greeter(helloworld_pb2_grpc.GreeterServicer):def SayHello(self, request, context):return helloworld_pb2.HelloReply(message=f"Hello, {request.name}")def serve():server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)server.add_insecure_port('[::]:50051')server.start()print("gRPC server running on port 50051...")server.wait_for_termination()if __name__ == '__main__':serve()
实现客户端:新建 client.py
import grpc
import helloworld_pb2
import helloworld_pb2_grpcdef run():with grpc.insecure_channel('localhost:50051') as channel:stub = helloworld_pb2_grpc.GreeterStub(channel)response = stub.SayHello(helloworld_pb2.HelloRequest(name="Alice"))print("Greeter client received:", response.message)if __name__ == '__main__':run()
启动方式
python server.py
# 另开终端
python client.py
输出结果
Greeter client received: Hello, Alice
RPC 与 gRPC 的关系与区别
维度 | RPC (泛指) | gRPC(具体实现) |
---|---|---|
概念 | 一种通信思想 / 模式 | Google 实现的开源高性能 RPC 框架 |
传输协议 | 不固定,可用 HTTP/TCP 等 | 固定基于 HTTP/2 |
序列化 | XML/JSON/自定义二进制等 | Protobuf(默认) |
语言支持 | 取决于具体 RPC 框架 | 官方支持多语言 |
IDL | 可以是 Thrift/IDL/自定义 | Proto 文件(.proto) |
性能 | 通常依赖实现 | gRPC 性能优异 |
流式支持 | 不一定 | 原生支持流式(stream)调用 |
生态工具 | 分散,因框架而异 | gRPC 官方提供丰富工具链 |