基础教程-简单案例(快入入门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 {@Overridepublic 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 {// 简单 RPCrpc 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 {@Overridepublic void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {String message = "Hello, " + request.getName();HelloResponse response = HelloResponse.newBuilder().setMessage(message).build();responseObserver.onNext(response);responseObserver.onCompleted();}@Overridepublic 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();}@Overridepublic StreamObserver<HelloRequest> uploadHelloRequests(StreamObserver<HelloResponse> responseObserver) {return new StreamObserver<HelloRequest>() {private final StringBuilder messages = new StringBuilder();@Overridepublic void onNext(HelloRequest request) {messages.append("Hello, ").append(request.getName()).append("\n");}@Overridepublic void onError(Throwable t) {t.printStackTrace();}@Overridepublic void onCompleted() {HelloResponse response = HelloResponse.newBuilder().setMessage(messages.toString()).build();responseObserver.onNext(response);responseObserver.onCompleted();}};}@Overridepublic StreamObserver<HelloRequest> chatHello(StreamObserver<HelloResponse> responseObserver) {return new StreamObserver<HelloRequest>() {@Overridepublic void onNext(HelloRequest request) {String message = "Hello, " + request.getName();HelloResponse response = HelloResponse.newBuilder().setMessage(message).build();responseObserver.onNext(response);}@Overridepublic void onError(Throwable t) {t.printStackTrace();}@Overridepublic 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();// 创建不同类型的 stubblockingStub = 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>() {@Overridepublic void onNext(HelloResponse response) {System.out.println("Stream response: " + response.getMessage());}@Overridepublic void onError(Throwable t) {t.printStackTrace();}@Overridepublic 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>() {@Overridepublic void onNext(HelloResponse response) {System.out.println("Response from server: " + response.getMessage());}@Overridepublic void onError(Throwable t) {t.printStackTrace();}@Overridepublic 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>() {@Overridepublic void onNext(HelloResponse response) {System.out.println("Response from server: " + response.getMessage());}@Overridepublic void onError(Throwable t) {t.printStackTrace();}@Overridepublic 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 {@Testpublic void testRpcMethod_simpleRpc(){HelloClient client = new HelloClient("localhost", 9090);// 简单 RPC 调用client.simpleRpc("Alice");}@Testpublic void testRpcMethod_serverStreamingRpc() throws InterruptedException {HelloClient client = new HelloClient("localhost", 9090);// 服务器端流式 RPC 调用client.serverStreamingRpc("Bob");TimeUnit.SECONDS.sleep(6);}@Testpublic void testRpcMethod_clientStreamingRpc() throws InterruptedException {HelloClient client = new HelloClient("localhost", 9090);// 客户端流式 RPC 调用client.clientStreamingRpc();TimeUnit.SECONDS.sleep(3);}@Testpublic void testRpcMethod_bidirectionalStreamingRpc() throws InterruptedException {HelloClient client = new HelloClient("localhost", 9090);// 双向流式 RPC 调用client.bidirectionalStreamingRpc();TimeUnit.SECONDS.sleep(3);}}
总结
以上代码示例分别实现了四种 RPC 类型:
- 简单 RPC:一次请求-响应。
- 服务器端流式 RPC:服务器返回一个流。
- 客户端流式 RPC:客户端发送一个流。
- 双向流式 RPC:客户端和服务器同时发送和接收流。
每种 RPC 类型的实现方式清晰,适用于不同的业务场景。