文章目录
RPC 是什么?
RPC(Remote Procedure Call,远程过程调用) 是一种计算机通信协议,允许程序像调用本地方法一样调用远程服务(比如另一台服务器上的函数)。它的核心目标是 让分布式系统的开发更简单,开发者无需关心底层网络通信细节。
RPC 的核心特点
特性 | 说明 |
---|---|
像本地调用一样简单 | 调用远程方法时,代码写法类似 result = service.Method(params) |
隐藏网络细节 | 序列化/反序列化、连接管理、超时重试等由 RPC 框架自动处理 |
支持多种协议 | 可以是 gRPC(HTTP/2 + Protobuf)、Thrift、Dubbo(TCP)、JSON-RPC 等 |
跨语言支持 | 客户端和服务端可以用不同语言编写(如 Go 调用 Python 服务) |
Proto 和 RPC 的关系
1. Proto(Protocol Buffers)是什么?
- 一种 数据序列化格式(类似 JSON/XML,但更高效)
- 通过
.proto
文件定义数据结构和服务接口 - 编译后会生成对应语言的代码(如 Go、Python、Java 的类和方法)
2. Proto 如何用于 RPC?
- 定义服务接口:在
.proto
文件中声明可远程调用的方法 - 生成代码:通过
protoc
工具生成客户端和服务端代码 - 实际通信:RPC 框架(如 gRPC)使用 Protobuf 序列化数据并通过网络传输
RPC 和 Proto 的协作流程
常见 RPC 框架
框架 | 协议 | 序列化 | 特点 |
---|---|---|---|
gRPC | HTTP/2 | Protobuf | Google 开源,高性能,跨语言 |
Thrift | TCP/HTTP | Thrift | Facebook 开源,支持多种协议 |
Dubbo | 自定义 | Hessian | 阿里开源,适合 Java 生态 |
JSON-RPC | HTTP | JSON | 简单,易调试 |
为什么用 Proto + gRPC?
- 性能高
- Protobuf 编码体积比 JSON 小 3-10 倍,解析速度快 5-100 倍
- 强类型接口
.proto
文件是明确的接口契约,减少前后端联调问题
- 跨语言
- 用同一份
.proto
文件生成多语言代码,保证数据一致性
- 用同一份
- 流式支持
- gRPC 支持双向流(如实时聊天、日志推送)
grpc项目实战
├─docs
│ ├─enums
│ ├─google
│ │ └─api
│ ├─model
│ └─xx
├─proto
│ ├─enums
│ ├─google
│ │ └─api
│ └─model
├─rpc
└─types
其中最重要的部分就是proto中的enums和model,其他文件都是生成出来的。
示例:Proto 定义 RPC 服务
// 1. 定义数据结构
message UserRequest {
string user_id = 1;
}
message UserResponse {
string name = 1;
int32 age = 2;
}
// 2. 定义 RPC 服务接口
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
}
编译后会生成:
UserRequest
和UserResponse
的序列化代码UserService
的客户端和服务端代码(包含GetUser
方法)
编译
SRC_PROTO := $(shell find ./proto -maxdepth 3 -type f)
.PHONY: rpc
rpc: ${SRC_PROTO}
protoc -I ./proto \
--go_out=./rpc --go-grpc_out=./rpc --grpc-gateway_out=./rpc \
--swagger_out=./docs \
--doc_out=./docs --doc_opt=markdown,chogori-grpc.md \
$^
.PHONY: html
html: ${SRC_PROTO}
protoc -I ./proto \
--go_out=./rpc --go-grpc_out=./rpc --grpc-gateway_out=./rpc \
--swagger_out=./docs \
--doc_out=./docs --doc_opt=html,index.html \
$^
1. 变量定义
SRC_PROTO := $(shell find ./proto -maxdepth 3 -type f)
- 作用:查找
./proto
目录及其子目录(最多3层)下的所有.proto
文件 - 输出示例:
./proto/example/v1/user.proto ./proto/example/v2/order.proto
2. rpc
目标
.PHONY: rpc
rpc: ${SRC_PROTO}
protoc -I ./proto \
--go_out=./rpc --go-grpc_out=./rpc --grpc-gateway_out=./rpc \
--swagger_out=./docs \
--doc_out=./docs --doc_opt=markdown,chogori-grpc.md \
$^
作用
-
生成 gRPC 代码:
--go_out
:生成 Protobuf 数据结构的 Go 代码(存放到./rpc
)--go-grpc_out
:生成 gRPC 服务端/客户端代码(存放到./rpc
)--grpc-gateway_out
:生成 gRPC-HTTP 网关代码(支持 RESTful API)
-
生成文档:
--swagger_out
:生成 Swagger/OpenAPI 文档(存放到./docs
)--doc_out
:生成 Markdown 格式的协议文档(文件名为chogori-grpc.md
)
使用方式:
make rpc # 执行后会更新所有生成的代码和文档
3. html
目标
.PHONY: html
html: ${SRC_PROTO}
protoc -I ./proto \
--go_out=./rpc --go-grpc_out=./rpc --grpc-gateway_out=./rpc \
--swagger_out=./docs \
--doc_out=./docs --doc_opt=html,index.html \
$^
作用:
与 rpc
目标类似,但将文档输出为 HTML 格式(index.html
)。
使用方式:
make html # 生成 HTML 文档
4. 典型工作流程
-
编写 Proto 文件
在./proto
目录下定义服务接口(如user.proto
) -
生成代码
make
-
实现业务逻辑
在生成的 Go 代码基础上编写服务端实现