gRPC通信原理与Protocol Buffers协议
请详细解释gRPC(Google Remote Procedure Call)的通信原理和Protocol Buffers(protobuf)协议格式。gRPC基于HTTP/2实现了哪些特性(多路复用、双向流)?protobuf相比JSON/XML有什么优势?定义一份简单的service和message并说明代码生成流程。
回答
我还是少年
gRPC核心原理
gRPC基于HTTP/2,使用Protocol Buffers作为接口定义语言(IDL)和序列化协议。
HTTP/2特性利用:
- 多路复用:单个TCP连接上多个gRPC调用并行
- 二进制帧:头部HPACK压缩,减少传输量
- 服务端推送:可主动推送数据
- 流控:HTTP/2内置流控制
四种通信模式:
- Unary RPC:客户端发送1个请求,服务端返回1个响应
- Server Streaming:客户端1个请求,服务端返回流式响应
- Client Streaming:客户端流式发送,服务端返回1个响应
- Bidirectional Streaming:双向流式通信
Protocol Buffers
syntax = "proto3";
package com.example;
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc ListUsers (ListUsersRequest) returns (stream User);
rpc UpdateUsers (stream UpdateUserRequest) returns (UpdateSummary);
rpc Chat (stream ChatMessage) returns (stream ChatMessage);
}
message User {
int32 id = 1;
string name = 2;
string email = 3;
repeated string roles = 4;
}
message GetUserRequest {
int32 user_id = 1;
}
protobuf vs JSON:
| 特性 | protobuf | JSON |
|---|---|---|
| 序列化大小 | 小(二进制,3-10倍小) | 大(文本) |
| 序列化速度 | 快(C++/Java原生实现) | 慢(反射+字符串解析) |
| 可读性 | 差(二进制) | 好(文本) |
| 版本兼容 | 支持(字段编号) | 手动处理 |
| 是否有Schema | 强制.proto文件 | 可选(Swagger/OpenAPI) |
| 语言支持 | 12+语言 | 所有语言 |
代码生成流程
# 1. 定义 .proto 文件
# 2. 编译生成Java代码
protoc --java_out=src/main/java user.proto
protoc --grpc-java_out=src/main/java user.proto
# 3. Maven/Gradle通过protobuf插件自动生成
# Maven: protobuf-maven-plugin
# Gradle: com.google.protobuf
Java服务端实现
class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
@Override
public void getUser(GetUserRequest request, StreamObserver<User> responseObserver) {
User user = User.newBuilder().setId(request.getUserId()).setName("Alice").build();
responseObserver.onNext(user);
responseObserver.onCompleted();
}
}