gRPC接入SpringBoot 2.x
对RPC有了初步了解之后,已知在高性能低延迟的场景下,可能RPC调用更适合作为系统服务之间的调用工具。
以下即为gRPC接入SpringBoot 的示例
一、创建server端project
framework | version |
SpringBoot | 2.5.8 |
gRPC | 1.42.2 |
protobuf-maven-plugin | 0.6.1 |
os-maven-plugin | 1.6.2 |
1、添加依赖
server端pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.ashe</groupId>
<artifactId>rpc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.13.1.RELEASE</version> <!-- 适用于 Spring Boot 2.x -->
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.42.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.42.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.42.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<!--suppress UnresolvedMavenProperty -->
<protocArtifact>com.google.protobuf:protoc:3.21.1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<!--suppress UnresolvedMavenProperty -->
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.48.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2、定义.proto文件
在项目的src/main/proto
目录下(如果没有则创建),定义你的服务.proto
文件(比如rpc.proto
)。
rpc.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "org.ashe.grpc";
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
3、生成代码
mvn clean compile
在target目录下可以看到生成的代码
4、创建sayHello服务
查看代码
@GrpcService
public class HelloServiceImpl extends org.ashe.grpc.HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(org.ashe.grpc.HelloRequest request, StreamObserver<org.ashe.grpc.HelloResponse> responseObserver) {
// 提供的服务就简单的hello一下,这里的getName是因为在.proto文件中定义了请求体中的name属性
String name = request.getName();
String message = "Hello, " + name;
org.ashe.grpc.HelloResponse response = org.ashe.grpc.HelloResponse.newBuilder()
.setMessage(message)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
从这里可以感受到RPC的理念是让开发者关注网络连接后的行为,不去关心网络连接的细节
二、创建client端project
1、添加依赖
client端pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.ashe</groupId>
<artifactId>rpc_client</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.70.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.70.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.70.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<!--suppress UnresolvedMavenProperty -->
<protocArtifact>com.google.protobuf:protoc:3.21.1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<!--suppress UnresolvedMavenProperty -->
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.48.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2、定义.proto文件
在项目的src/main/proto
目录下(如果没有则创建),定义你的服务.proto
文件(比如client.proto
)。
client.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "org.ashe";
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
3、生成代码
mvn clean compile
4.Main方法调用server端的sayHello服务
查看代码
package org.ashe;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class App {
public static void main(String[] args) {
// port要对应上server端应用的port
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost",9090)
.usePlaintext()
.build();
org.ashe.HelloServiceGrpc.HelloServiceBlockingStub stub = org.ashe.HelloServiceGrpc.newBlockingStub(channel);
org.ashe.HelloRequest request = org.ashe.HelloRequest.newBuilder().setName("Obama").build();
org.ashe.HelloResponse response = stub.sayHello(request);
System.out.println("Response: " + response.getMessage());
channel.shutdown();
}
}