一、gRPC 简介
1.1 定义与特点
gRPC 是由 Google 开发的高性能远程过程调用(RPC)框架,它允许开发者像调用本地函数一样调用远程服务器上的方法。其主要特点包括:
- 快速高效:采用 HTTP/2 作为传输协议,支持双向流式通信。
- 跨语言支持:提供多种编程语言的客户端和服务端库,如 Java、Python、Go 等。
- 统一接口定义:通过
.proto
文件定义服务接口,确保客户端和服务端的一致性。
1.2 应用场景
gRPC 特别适用于以下场景:
- 微服务架构:实现服务间的高效通信。
- 多语言系统:不同语言编写的系统间需要进行交互。
- 实时通信:需要双向流或实时数据传输的应用。
二、gRPC 的核心组件
2.1 .proto 文件
.proto
文件是 gRPC 的接口定义文件,相当于一个合同,规定了服务及其方法的定义和数据结构。它的作用包括:
- 统一接口:客户端和服务端基于同一个
.proto
文件生成代码,避免接口不一致的问题。 - 跨语言支持:一个
.proto
文件可以生成多种语言的代码,如 Python、Go、Java 等。 - 自动序列化:使用 Protobuf 自动将对象转换为二进制格式进行传输。
示例 .proto
文件
syntax = "proto3";
package example;
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
}
message UserRequest {
int32 id = 1;
}
message UserResponse {
string name = 1;
int32 age = 2;
}
2.2 Protobuf 序列化协议
Protobuf 是 gRPC 默认使用的数据序列化协议,是一种高效的二进制序列化协议。相比 JSON 等文本格式,Protobuf 生成的数据体积更小,适用于移动应用与后端之间的内部通信,是高性能、低功耗通信的优选方案。
序列化与反序列化流程
- 序列化:将内存中的对象(如
User
对象)转换成二进制字节流。 - 反序列化:将二进制字节流转回对象。
三、gRPC 工作原理
3.1 客户端与服务端交互流程
客户端流程
- 调用
stub.getUser(123)
方法。 - gRPC 框架使用 Protobuf 将请求对象序列化成二进制格式。
- 通过 HTTP/2 协议发送出去。
服务端流程
- gRPC 收到数据。
- 使用 Protobuf 反序列化成对象。
- 调用你实现的业务逻辑。
- 再用 Protobuf 序列化响应并返回。
3.2 图解交互流程
客户端:
1. 你调用 stub.getUser(123)
2. gRPC 框架 → 使用 Protobuf 把请求对象序列化成二进制
3. 通过 HTTP/2 发送出去
网络中传输:二进制字节流(由 Protobuf 生成)
服务端:
1. gRPC 收到数据
2. 使用 Protobuf 反序列化成对象
3. 调用你实现的业务逻辑
4. 再用 Protobuf 序列化响应 → 返回
四、Java 中使用 gRPC 的步骤
4.1 创建 .proto
文件
在 Java 项目中,.proto
文件通常放在与 Java 包同级的 proto
目录下。
4.2 生成代码
使用 Maven 插件自动生成代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 项目基本信息 -->
<groupId>com.example</groupId>
<artifactId>grpc-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>grpc-demo</name>
<description>gRPC 服务端与客户端演示项目</description>
<properties>
<!-- 全局版本控制 -->
<java.version>8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- gRPC 相关依赖版本 -->
<grpc.version>1.50.2</grpc.version>
<protobuf.version>3.21.12</protobuf.version>
<os-maven-plugin.version>1.7.1</os-maven-plugin.version>
<protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
</properties>
<dependencies>
<!-- gRPC 核心依赖 -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>${grpc.version}</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<!-- 用于检测操作系统类型(跨平台支持) -->
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
</extension>
</extensions>
<plugins>
<!-- 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Protobuf 代码生成插件 -->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf-maven-plugin.version}</version>
<configuration>
<!-- 指定 protoc 编译器 -->
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
<!-- gRPC Java 插件 -->
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
<!-- 生成的 Java 文件输出路径 -->
<outputDirectory>src/main/java</outputDirectory>
<!-- 不清空输出目录,避免覆盖已有代码 -->
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- 编译 .proto 生成 Message 类 -->
<goal>compile-custom</goal> <!-- 使用插件生成 gRPC Stub/Service -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
4.3 实现业务逻辑
生成的代码类似 service
接口,你需要自己编写实现类来处理具体的业务逻辑。
总结
gRPC 是一种强大的 RPC 框架,结合 Protobuf 序列化协议,能够实现高效、跨语言的远程调用。通过 .proto
文件定义接口,确保了客户端和服务端的一致性,并支持多种编程语言的开发。希望本文能帮助你更好地理解和使用 gRPC。