spring 和 grpc 的整合
spring 和 grpc 的整合
首先我们要知道 grpc 中我们在使用的时候用到了 grpc 的那些东西
- dil 的编写
- serverimpl
- serverbuilder
- addService
- 客户端的 stub 编写
这里面我们看一下我们那些地方可能需要 spring 帮我们管理,那些地方我们需要自己来管理呢?比如服务的构建 spring
是可以帮我么做的,而且 addServer 可以通过注解的方式自动发布服务,但是 server 的 imp 我们是需要自己来实现的,服务的端口可以通过 properties 的方式来做自动配置和默认值的设置。注解的标识 spring 使用 @GrpcService
服务端搭建开发环境
- spring的开发环境我们需要搭建,这个可以直接在 idea 创建,我就不记录和展示
- 引入 grpc spring 相关的依赖
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.15.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.25.5</version>
</dependency>
因为这是一个 grpc 的 server 所以并不需要使用 java-web 相关的服务,我们可以移除相关的依赖,并且在配置中禁用 web 相关的内容
配置 & 移除 web 相关的内容
grpc:
server:
port: 8888
-- 禁用 web 的服务
spring:
application:
name: grpc-server
main:
web-application-type: none
server:
port: 9999
移除对应的依赖在 pom 文件中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
</exclusions>
</dependency>
这个时候我们就可以使用了,使用注解 @GrpcServer
使其在 springboot 中可以被注入 IOC 容器,然后就是很传统的实现 **ImplBase
并且她也会帮我们把这个服务发布到 GRPC 服务中 addServer
这样 springboot 启动就会自动提供服务接受 grpc client 发送来的请求。
@GrpcService
public class OnceMessageServiceImpl extends BiRpcServiceGrpc.BiRpcServiceImplBase {
private final Logger log = LoggerFactory.getLogger(OnceMessageServiceImpl.class);
@Override
public void getOnceMessage(final BiService.OnceMessageRequest request, final StreamObserver<BiService.OnceMessageResponse> responseObserver) {
log.info("receive client request msg -> {}", request.getContent());
responseObserver.onNext(
BiService.OnceMessageResponse.newBuilder().setContent(UUID.randomUUID().toString()).build()
);
responseObserver.onCompleted();
}
}
syntax = "proto3";
option java_package = "com.rpc.grpc.bi";
option java_multiple_files = false;
option java_outer_classname = "BiService";
message OnceMessageRequest {
string content = 1;
}
message OnceMessageResponse {
string content = 1;
}
service BiRpcService {
// 注意这里因为我们使用 future 的方式来通讯,这就不可以使用 stream,只能使用简单的 rpc
rpc getOnceMessage(OnceMessageRequest) returns (OnceMessageResponse) {}
}
service NewBiRpcService {
// 注意这里因为我们使用 future 的方式来通讯,这就不可以使用 stream,只能使用简单的 rpc
rpc newGetOnceMessage(OnceMessageRequest) returns (OnceMessageResponse) {}
}
客户端搭建
引入依赖
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
增加配置
spring:
application:
name: grpc-rpc-boot-client
grpc:
client:
bi_server:
address: static://localhost:8888
negotiation-type: plaintext
server:
port: 8989
编码
由于 spring 以及对客户端的服务创建,等配置做了封装,所以我们并不需要关心 channel 的创建,我们直接注入对应的 stub(这里有三种 stub,分别是 future,stub,block),直接使用注解 @GrpcClient 然后在里面放我们在配置文件中配置的服务名称,直接就可以通过 stub 调用了,然后 channel 的关闭等操作我们也不用关心,这个已经做好了相关的封装,使用者直接关心业务层面的逻辑就可以了。
public class BiRpcServerBlockStub {
@GrpcClient("bi_server")
private BiRpcServiceGrpc.BiRpcServiceBlockingStub biRpcServiceBlockingStub;
@GetMapping
public Object getUserInfo(String msg) {
final BiService.OnceMessageResponse onceMessage = biRpcServiceBlockingStub.getOnceMessage(
BiService.OnceMessageRequest.newBuilder()
.setContent(msg).build()
);
return onceMessage.getContent();
}
}
大家可以关注我的WX