高性能!Spring 官方支持 gRPC,三行代碼搞定
環(huán)境:SpringBoot3.4.2
1. 簡介
什么是gRPC?
gRPC 是一個現(xiàn)代化的開源高性能遠(yuǎn)程過程調(diào)用(RPC)框架,可在任何環(huán)境中運行。它能夠通過可插拔的負(fù)載均衡、追蹤、健康檢查和認(rèn)證支持,高效地連接數(shù)據(jù)中心內(nèi)部和跨數(shù)據(jù)中心的服務(wù)。同時,它也適用于分布式計算的“最后一公里”,用于連接設(shè)備、移動應(yīng)用和瀏覽器與后端服務(wù)。
Spring gRPC
Spring gRPC 項目為開發(fā) gRPC 應(yīng)用程序提供了一個與 Spring 生態(tài)兼容的 API 和抽象層。該項目包含一個核心庫,它使得在 gRPC 中使用依賴注入變得輕而易舉,此外還有一個 Spring Boot 啟動器(starter),它能讓你輕松地在 Spring Boot 應(yīng)用程序中開始使用 gRPC。
接下來,我們將通過Spring gRPC詳細(xì)的實現(xiàn)一個RPC調(diào)用。
2.實戰(zhàn)案例
2.1 準(zhǔn)備依賴
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.grpc</groupId>
<artifactId>spring-grpc-server-web-spring-boot-starter</artifactId>
</dependency>同時,我們還需要配置build,這樣我們可以直接通過proto文件生成對應(yīng)的java文件
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<buildArgs>
<buildArg>--verbose</buildArg>
</buildArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>${spring-javaformat-maven-plugin.version}</version>
<executions>
<execution>
<?m2e ignore?>
<phase>validate</phase>
<inherited>true</inherited>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.github.ascopes</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<protocVersion>${protobuf-java.version}</protocVersion>
<binaryMavenPlugins>
<binaryMavenPlugin>
<groupId>io.grpc</groupId>
<artifactId>protoc-gen-grpc-java</artifactId>
<version>${grpc.version}</version>
<classifier>${os.detected.classifier}</classifier>
<options>jakarta_omit,@generated=omit</options>
</binaryMavenPlugin>
</binaryMavenPlugins>
<outputDirectory>src/main/java</outputDirectory>
</configuration>
<executions>
<execution>
<?m2e execute onConfiguration,onIncremental?>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>2.2 編寫proto文件
在src/main/protobuf目錄下新建hello.proto文件,內(nèi)容如下:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.pack.grpc.proto";
option java_outer_classname = "HelloWorldProto";
// 定義服務(wù)
service Simple {
// 發(fā)生消息
rpc SayHello(HelloRequest) returns (HelloReply) {}
rpc StreamHello(HelloRequest) returns (stream HelloReply) {}
}
// 請求消息
message HelloRequest {
string name = 1;
}
// 響應(yīng)消息
message HelloReply {
string message = 1;
}2.3 根據(jù)proto生成java文件
接下來,我們需要在項目的根目錄下執(zhí)行如下的命令:
mvnw clean package執(zhí)行完成后,將生成的java文件保存到 src/main/java下的com.pack.grpc.proto包中,如下所示:
圖片
2.4 定義gRPC服務(wù)
@Service
public class GrpcServerService extends SimpleGrpc.SimpleImplBase {
private static Logger log = LoggerFactory.getLogger(GrpcServerService.class);
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
log.info("Hello, {}", req.getName());
if (req.getName().startsWith("error")) {
throw new IllegalArgumentException("Bad name: " + req.getName());
}
if (req.getName().startsWith("internal")) {
throw new RuntimeException();
}
HelloReply reply = HelloReply.newBuilder().setMessage("Hello ==> " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
@Override
public void streamHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
log.info("Hello, {}", req.getName());
int count = 0;
while (count < 10) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello(" + count + ") ==> " + req.getName()).build();
responseObserver.onNext(reply);
count++;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
responseObserver.onError(e);
return;
}
}
responseObserver.onCompleted();
}
}下面配置該服務(wù)地址信息:
spring:
grpc:
server:
host: 0.0.0.0
port: 9090
ssl:
secure: false
enabled: false
servlet:
enabled: false通過上面的配置,我們的gRPC服務(wù)將運行在9090端口上。
圖片
2.5 定義gRPC客戶端
客戶端導(dǎo)入上面通過proto生成java文件后,我們只需要定義如下的bean即可:
@Configuration
public class GRpcConfig {
@Bean
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
//return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090"));
//也可以通過命名通道方式
return SimpleGrpc.newBlockingStub(channels.createChannel("local"));
}
}接下來,還需要在配置文件中進(jìn)行如下配置:
spring:
grpc:
client:
default-channel:
secure: false
ssl:
enabled: false
channels:
local:
address: 0.0.0.0:9090以上我們就完成了gRPC server/client所有代碼。
2.6 測試
在客戶端,我們只需要注入上面定義的:SimpleGrpc.SimpleBlockingStub bean就可以使用了。
@RestController
@RequestMapping("/grpc")
public class GrpcController {
private final SimpleGrpc.SimpleBlockingStub stub;
public GrpcController(SimpleBlockingStub stub) {
this.stub = stub;
}
@GetMapping("/invoke")
public ResponseEntity<?> invoke(String message) throws Exception {
HelloRequest request = HelloRequest.newBuilder()
.setName(message)
.build();
return ResponseEntity.ok(stub.sayHello(request).getMessage());
}
}輸出結(jié)果
圖片
成功?。?!





























