基础教程-简单案例(快入入门java-grpc框架)
参考官方入门案例教程:里面我看proto编译,其实直接用maven就能直接将.proto文件编译成java代码。
快速入门 | Java | gRPC 框架https://grpc.org.cn/docs/languages/java/quickstart/
目录结构
src/
├── main/
│ ├── proto/
│ │ └── hello.proto # Proto 文件
│ ├── java/
│ │ ├── com/yuan/springboot/grpc/
│ │ │ ├── HelloServiceImpl.java # 服务端实现
│ │ │ ├── GrpcServer.java # 服务端主类
│ │ │ ├── GrpcClient.java # 客户端实现
│ │ │ ├── MainApplication.java # 项目入口(可选)
Step 1: 配置maven依赖
<properties>
<grpc.version>1.6.1</grpc.version>
<protobuf.version>3.3.0</protobuf.version>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency>
<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>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Step 2: 创建 Proto 文件
注意:
将你的 hello.proto
文件放在 src/main/proto/hello.proto
路径下。
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.yuan.springboot.grpc";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
service HelloService {
rpc sayHello(HelloRequest) returns (HelloResponse);
}
通过maven的compile直接就能编译如图:
Step 3: 实现服务端
HelloServiceImpl.java(
com.yuan.springboot.grpc)
package com.yuan.springboot.grpc;
import io.grpc.stub.StreamObserver;
/**
* @author liuyuan on 2025/1/15
* 服务端实现
*/
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String message = "Hello, " + request.getName() + "!";
HelloResponse response = HelloResponse.newBuilder()
.setMessage(message)
.build();
// 返回响应
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
GrpcServer.java(com.yuan.springboot.grpc)
package com.yuan.springboot.grpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
/**
* @author liuyuan on 2025/1/15
* 服务端主类
*/
public class GrpcServer {
public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(9090)
.addService(new HelloServiceImpl())
.build();
System.out.println("Server started on port 9090");
server.start();
server.awaitTermination();
}
}
Step 4: 实现客户端
GrpcClient.java(com.yuan.springboot.grpc)
package com.yuan.springboot.grpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
/**
* @author liuyuan on 2025/1/15
* 客户端实现
*/
public class GrpcClient {
public static void main(String[] args) {
// 创建 gRPC 通道
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090)
.usePlaintext(true)
.build();
// 创建存根
HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);
// 构造请求
HelloRequest request = HelloRequest.newBuilder()
.setName("World")
.build();
// 调用远程方法
HelloResponse response = stub.sayHello(request);
System.out.println("Response from server: " + response.getMessage());
// 关闭通道
channel.shutdown();
}
}
Step 5: 启动服务端和客户端
1、在 IntelliJ IDEA 中运行 GrpcServer.java
,启动服务端,如图:
2、在 IntelliJ IDEA 中运行 GrpcClient.java
,启动客户端,如图:
基础教程-定义rpc方法
在服务定义中定义 rpc
方法,指定它们的请求和响应类型。gRPC 允许你定义四种服务方法
1. 简单 RPC (Simple RPC)
- 方法名:
sayHello
- 描述: 客户端发送一个请求,服务器返回一个响应。
rpc sayHello(HelloRequest) returns (HelloResponse);
2. 服务器端流式 RPC (Server-side Streaming RPC)
- 方法名:
streamHelloResponses
- 描述: 客户端发送一个请求,服务器返回一个流,客户端从流中读取多个响应。
rpc streamHelloResponses(HelloRequest) returns (stream HelloResponse);
3. 客户端流式 RPC (Client-side Streaming RPC)
- 方法名:
uploadHelloRequests
- 描述: 客户端发送一个请求流,服务器返回一个单一的响应。
rpc uploadHelloRequests(stream HelloRequest) returns (HelloResponse);
4. 双向流式 RPC (Bidirectional Streaming RPC)
- 方法名:
chatHello
- 描述: 客户端和服务器通过流进行双向通信,客户端和服务器可以独立发送和接收消息。
rpc chatHello(stream HelloRequest) returns (stream HelloResponse);
四种rpc方法案例
step1 proto文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.yuan.springboot.grpc";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
service HelloService {
// 简单 RPC
rpc sayHello(HelloRequest) returns (HelloResponse);
// 服务器端流式 RPC (Server-side Streaming RPC)
rpc streamHelloResponses(HelloRequest) returns (stream HelloResponse);
// 客户端流式 RPC (Client-side Streaming RPC)
rpc uploadHelloRequests(stream HelloRequest) returns (HelloResponse);
// 双向流式 RPC (Bidirectional Streaming RPC)
rpc chatHello(stream HelloRequest) returns (stream HelloResponse);
}
step2 实现定义的rpc方法(服务端实现)
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String message = "Hello, " + request.getName();
HelloResponse response = HelloResponse.newBuilder()
.setMessage(message)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
@Override
public void streamHelloResponses(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String name = request.getName();
for (int i = 1; i <= 5; i++) {
HelloResponse response = HelloResponse.newBuilder()
.setMessage("Hello, " + name + "! Message " + i)
.build();
responseObserver.onNext(response);
// 模拟延迟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
responseObserver.onCompleted();
}
@Override
public StreamObserver<HelloRequest> uploadHelloRequests(StreamObserver<HelloResponse> responseObserver) {
return new StreamObserver<HelloRequest>() {
private final StringBuilder messages = new StringBuilder();
@Override
public void onNext(HelloRequest request) {
messages.append("Hello, ").append(request.getName()).append("\n");
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
HelloResponse response = HelloResponse.newBuilder()
.setMessage(messages.toString())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
};
}
@Override
public StreamObserver<HelloRequest> chatHello(StreamObserver<HelloResponse> responseObserver) {
return new StreamObserver<HelloRequest>() {
@Override
public void onNext(HelloRequest request) {
String message = "Hello, " + request.getName();
HelloResponse response = HelloResponse.newBuilder()
.setMessage(message)
.build();
responseObserver.onNext(response);
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
}
step3 客户端实现
public class HelloClient {
private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;
private final HelloServiceGrpc.HelloServiceStub asyncStub;
public HelloClient(String host, int port) {
// 创建 gRPC 通道
ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext(true) // 不使用 SSL,开发环境下推荐
.build();
// 创建不同类型的 stub
blockingStub = HelloServiceGrpc.newBlockingStub(channel);
asyncStub = HelloServiceGrpc.newStub(channel);
}
// 简单 RPC 示例
public void simpleRpc(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloResponse response = blockingStub.sayHello(request);
System.out.println("Response from server: " + response.getMessage());
}
// 服务器端流式 RPC 示例
public void serverStreamingRpc(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
asyncStub.streamHelloResponses(request, new io.grpc.stub.StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse response) {
System.out.println("Stream response: " + response.getMessage());
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Stream completed");
}
});
}
// 客户端流式 RPC 示例
public void clientStreamingRpc() {
io.grpc.stub.StreamObserver<HelloRequest> requestObserver = asyncStub.uploadHelloRequests(
new io.grpc.stub.StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse response) {
System.out.println("Response from server: " + response.getMessage());
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Stream completed");
}
});
requestObserver.onNext(HelloRequest.newBuilder().setName("Alice").build());
requestObserver.onNext(HelloRequest.newBuilder().setName("Bob").build());
requestObserver.onCompleted();
}
// 双向流式 RPC 示例
public void bidirectionalStreamingRpc() {
io.grpc.stub.StreamObserver<HelloRequest> requestObserver = asyncStub.chatHello(
new io.grpc.stub.StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse response) {
System.out.println("Response from server: " + response.getMessage());
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {
System.out.println("Stream completed");
}
});
requestObserver.onNext(HelloRequest.newBuilder().setName("Alice").build());
requestObserver.onNext(HelloRequest.newBuilder().setName("Bob").build());
requestObserver.onCompleted();
}
}
step4 案例测试
public class MainTest {
@Test
public void testRpcMethod_simpleRpc(){
HelloClient client = new HelloClient("localhost", 9090);
// 简单 RPC 调用
client.simpleRpc("Alice");
}
@Test
public void testRpcMethod_serverStreamingRpc() throws InterruptedException {
HelloClient client = new HelloClient("localhost", 9090);
// 服务器端流式 RPC 调用
client.serverStreamingRpc("Bob");
TimeUnit.SECONDS.sleep(6);
}
@Test
public void testRpcMethod_clientStreamingRpc() throws InterruptedException {
HelloClient client = new HelloClient("localhost", 9090);
// 客户端流式 RPC 调用
client.clientStreamingRpc();
TimeUnit.SECONDS.sleep(3);
}
@Test
public void testRpcMethod_bidirectionalStreamingRpc() throws InterruptedException {
HelloClient client = new HelloClient("localhost", 9090);
// 双向流式 RPC 调用
client.bidirectionalStreamingRpc();
TimeUnit.SECONDS.sleep(3);
}
}
总结
以上代码示例分别实现了四种 RPC 类型:
- 简单 RPC:一次请求-响应。
- 服务器端流式 RPC:服务器返回一个流。
- 客户端流式 RPC:客户端发送一个流。
- 双向流式 RPC:客户端和服务器同时发送和接收流。
每种 RPC 类型的实现方式清晰,适用于不同的业务场景。