@[toc]
目录
一、环境准备
二、gRPC项目构建
创建proto文件
生成Java类
创建模块local-server(gRPC服务端)
创建模块local-client(gRPC客户端)
调用效果
安装protocbuf
下载地址
https://github.com/protocolbuffers/protobuf/releases
选择对应的版本下载安装,这里我选择21.1
选择对应的压缩包解压
配置环境变量
变量名 :PROTOCBUF_HOME
变量值:D:\protoc-21.1-win64
找到系统变量中的path变量,选中后点击编辑,新增:%PROTOBUF_HOME%\bin
安装protocbuf插件
Protobuf - IntelliJ IDEs Plugin | Marketplace
从idea官网下载插件
选择idea对应的版本下载
项目目录结构
项目结构
创建maven父工程spring-boot-grpc
完整pom.xml
4.0.0
pom
spring-boot-grpc-lib
local-server
local-client
org.springframework.boot
spring-boot-starter-parent
2.6.1
org.example
spring-boot-grpc
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
UTF-8
org.springframework.boot
spring-boot-maven-plugin
2.6.1
创建模块spring-boot-grpc-lib
此模块负责将.proto文件生成Java对应的类与接口
根据官方文档
选择对应的版本查看README.md
可以根据提交历史查看具体proto版本对应的pom.xml
完整pom.xml
org.example
spring-boot-grpc
1.0-SNAPSHOT
4.0.0
com.example
spring-boot-grpc-lib
0.0.1-SNAPSHOT
spring-boot-grpc-lib
Demo project for Spring Boot
1.8
UTF-8
UTF-8
io.grpc
grpc-netty-shaded
1.42.1
io.grpc
grpc-protobuf
1.42.1
io.grpc
grpc-stub
1.42.1
org.apache.tomcat
annotations-api
6.0.53
provided
com.google.protobuf
protobuf-java
3.17.2
com.google.protobuf
protobuf-java-util
3.17.2
javax.annotation
javax.annotation-api
1.3.2
io.grpc
grpc-bom
1.42.2
pom
import
kr.motd.maven
os-maven-plugin
1.6.2
org.xolstice.maven.plugins
protobuf-maven-plugin
0.6.1
com.google.protobuf:protoc:3.17.2:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:1.42.1:exe:${os.detected.classifier}
compile
compile-custom
在spring-boot-grpc-lib模块的src/main/proto目录下新增名为helloworld.proto的文件
这里面定义了一个gRPC服务,里面含有一个接口,并且还有这个接口的入参和返回结果的定义
proto文件夹需要在 File -> ProjectStructure 中将其标记为sources
syntax = "proto3"; // 协议版本
// 选项配置
option java_multiple_files = true;
option java_package = "com.example.springbootgrpclib.grpc.protobuf";
option java_outer_classname = "SimpleProto";
service Simple {
// 简单gRPC
rpc OneToOne (MyRequest) returns (MyResponse) {
}
}
message MyRequest {
string name = 1;
int32 value = 2;
}
message MyResponse {
string message = 1;
int64 result = 2;
}
idea 单击编译类
生成对应的类并且将其复制到spring-boot-grpc-lib下
spring-boot-grpc-lib结构:
在父工程下面新建名为local-server的springboot模块,
添加gRPC 服务端 Maven 依赖和spring-boot-grpc-lib模块
完整pom.xml
4.0.0
org.example
spring-boot-grpc
1.0-SNAPSHOT
com.example
local-server
0.0.1-SNAPSHOT
local-server
Demo project for Spring Boot
11
UTF-8
UTF-8
2.6.1
org.projectlombok
lombok
true
net.devh
grpc-server-spring-boot-starter
2.13.0.RELEASE
com.example
spring-boot-grpc-lib
0.0.1-SNAPSHOT
springboot配置文件 application.yml
spring:
application:
name: spring-boot-grpc-server
# gRPC有关的配置,这里只需要配置服务端口号
grpc:
server:
port: 9898
server:
port: 8080
增加启动类RpcServerApplication
package com.example.localserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RpcServerApplication {
public static void main(String[] args) {
SpringApplication.run(RpcServerApplication.class, args);
}
}
在service类中将gRPC服务对外暴露出去
完整代码如下
package com.example.localserver.server;
import com.example.springbootgrpclib.grpc.protobuf.MyRequest;
import com.example.springbootgrpclib.grpc.protobuf.MyResponse;
import com.example.springbootgrpclib.grpc.protobuf.SimpleGrpc;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
@Slf4j
public class GrpcServerService extends SimpleGrpc.SimpleImplBase {
@Override
public void oneToOne(MyRequest request, StreamObserver responseObserver) {
log.info("接收客户端数据{}", request);
MyResponse response = MyResponse.newBuilder().setMessage( request.getName()).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
上述GrpcServerService.java中有几处需要注意:
是使用@GrpcService注解,再继承SimpleImplBase,这样就可以借助grpc-server-spring-boot-starter库将oneToOne暴露为gRPC服务;
SimpleImplBase是前文中根据proto自动生成的java代码,在spring-boot-grpc-lib模块中;
oneToOne方法中处理完毕业务逻辑后,调用responseObserver.onNext方法填入返回内容;
调用responseObserver.onCompleted方法表示本次gRPC服务完成;
至此,gRPC服务端编码就完成了,服务端流、客户端流和双向流在后面介绍。
在父工程grpc-turtorials下面新建名为local-client的模块
添加gRPC客户端 Maven 依赖和spring-boot-grpc-lib模块
完整pom.xml
4.0.0
org.example
spring-boot-grpc
1.0-SNAPSHOT
com.example
local-client
0.0.1-SNAPSHOT
local-client
Demo project for Spring Boot
11
UTF-8
UTF-8
2.6.1
net.devh
grpc-client-spring-boot-starter
2.13.0.RELEASE
com.example
spring-boot-grpc-lib
0.0.1-SNAPSHOT
org.projectlombok
lombok
true
springboot配置文件 application.yml:
server:
port: 8088
spring:
application:
name: local-client
grpc:
client:
# gRPC配置的名字,GrpcClient注解会用到
local-grpc-server:
# gRPC服务端地址
address: 'static://127.0.0.1:9898'
enableKeepAlive: true
keepAliveWithoutCalls: true
negotiationType: plaintext
启动类RpcClientApplication
package com.example.localclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RpcClientApplication {
public static void main(String[] args) {
SpringApplication.run(RpcClientApplication.class, args);
}
}
服务类GrpcClientService
package com.example.localclient.service;
import com.example.springbootgrpclib.grpc.protobuf.MyRequest;
import com.example.springbootgrpclib.grpc.protobuf.MyResponse;
import com.example.springbootgrpclib.grpc.protobuf.SimpleGrpc;
import io.grpc.StatusRuntimeException;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class GrpcClientService {
@GrpcClient("local-grpc-server")
private SimpleGrpc.SimpleBlockingStub simpleStub;
public String oneToOne(final String name) {
try {
final MyResponse response = this.simpleStub.oneToOne(MyRequest.newBuilder().setName(name).build());
return response.getMessage();
} catch (final StatusRuntimeException e) {
return "FAILED with " + e.getStatus().getCode().name();
}
}
}
上述GrpcClientService类有几处要注意的地方:
用@Service将GrpcClientService注册为spring的普通bean实例;
用@GrpcClient修饰SimpleBlockingStub,这样就可以通过grpc-client-spring-boot-starter库发起gRPC调用,被调用的服务端信息来自名为local-grpc-server的配置;
SimpleBlockingStub来自前文中根据helloworld.proto生成的java代码;
SimpleBlockingStub.oneToOne方法会远程调用local-server应用的gRPC服务;
新增controller层验证gRPC服务调用能否成功
package com.example.localclient.controller;
import com.example.localclient.service.GrpcClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author cdj
* @date 2022/4/11 - 17:36
**/
@RestController
public class GrpcClientController {
@Autowired
private GrpcClientService grpcClientService;
@RequestMapping("/oneToOne")
public String oneToOne(@RequestParam(defaultValue = "name") String name) {
return grpcClientService.oneToOne(name);
}
}
http://127.0.0.1:8088/oneToOne?name=rpc-test