赞
踩
最近公司其他服务为go语言开发,这边Java服务需要进行交互,考虑到效率和系统发展的问题,因此使用了gRPC来作为rpc框架。由于基本是第一次使用Springboot集成gRPc,经过一系列的踩坑,终于完成了项目的开发,这边记录下整合方式。
gRPC是谷歌开源的基于go语言的一个现代的开源高性能RPC框架,可以在任何环境中运行。它可以有效地连接数据中心内和跨数据中心的服务,并提供可插拔的支持,以实现负载平衡,跟踪,健康检查和身份验证。它还适用于分布式计算的最后一英里,用于将设备,移动应用程序和浏览器连接到后端服务。
Protocol Buffers是一个跨语言、跨平台的具有可扩展机制的序列化数据工具。也就是说,我在ubuntu下用python语言序列化一个对象,并使用http协议传输到使用java语言的android客户端,java使用对用的代码工具进行反序列化,也可以得到对应的对象。可以根据客户端与服务端约定同一个Proto文件进行交互,然后双方可以根据proto文件反序列化为相应语言的对象进行交互。只是这个对象可能是自动生成的,会有点点不适应。
Grpc Spring Boot Starter地址:https://github.com/yidongnan/grpc-spring-boot-starter
<properties> <java.version>1.8</java.version> <grpc.version>1.6.1</grpc.version> <protobuf.version>3.3.0</protobuf.version> </properties> <!-- google.protobuf --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>com.google.api.grpc</groupId> <artifactId>proto-google-common-protos</artifactId> <version>1.12.0</version> </dependency> <dependency> <groupId>com.googlecode.protobuf-java-format</groupId> <artifactId>protobuf-java-format</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-all</artifactId> <version>1.17.0</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-client-spring-boot-starter</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.6-jre</version> </dependency>
<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> <!--默认值--> <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot> <outputDirectory>${project.basedir}/src/main/java</outputDirectory> <clearOutputDirectory>false</clearOutputDirectory> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin>
syntax = "proto3"; option java_multiple_files = true; option java_package = "com.aiccms.device.grpc.lib"; option java_outer_classname = "DeviceFixProto"; option objc_class_prefix = "HLW"; package device; // The device service definition. service DeviceFixService { // Sends a message rpc insertDeviceFix (deviceFix) returns (booleanReply){} rpc updateDeviceFix (deviceFix) returns (booleanReply){} rpc searchDeviceFix (conditionsRequest) returns (deviceFix){} rpc deleteDeviceFix (conditionsRequest) returns (booleanReply){} } // The request message . message conditionsRequest { string id = 1; } message deviceFix { string id=1; string serialNum=2; string userNum=3; int32 status=4; int32 type=5; string address=6; string createtime=7; string updatetime=8; } // The response message message booleanReply { bool reply = 1; } // The response message message objectReply { bool reply = 1; }
使用mvn命令 protobuf:compile 和protobuf:compile-custom命令编译生成java文件
将会根据proto文件生成对应的Java对象。
@Slf4j
@GrpcService()
public class DeviceGrpcService extends DeviceFixServiceGrpc.DeviceFixServiceImplBase {
@Override
public void insertDeviceFix(deviceFix request, StreamObserver<booleanReply> responseObserver) {
// 返回体构建,入参在request中,这边省略业务代码
booleanReply reply = booleanReply.newBuilder().build();
// 返回参数
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
继承生成对象,具体实现其中定义好的方法,即双方在文件中约定好的参数以及接口。
定义grpc服务端接口。
grpc:
server:
port: 9090
public class DeviceGrpcClient { /** * 阻塞模式 * 拦截器需要在注解里写明 */ @GrpcClient(value = "myservice", interceptors = HeaderClientInterceptor.class) DeviceFixServiceGrpc.DeviceFixServiceBlockingStub deviceFixServiceBlockingStub; /** * 其中定义好的一个接口 * * @param request * @return */ public booleanReply insertDeviceFix(deviceFix request) { // 业务代码 return deviceFixServiceBlockingStub.insertDeviceFix(request); } }
客户端可以实现自定义拦截器,在数据抵达channel之前对数据拦截做一些相关操作,服务端也可以实现相应拦截器,双方做一些数据的交互。
@GrpcGlobalClientInterceptor @Slf4j public class HeaderClientInterceptor implements ClientInterceptor { @Override public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>( next.newCall(method, callOptions)) { @Override public void start(Listener<RespT> responseListener, Metadata headers) { // 这边可以将自己需要的请求头传入,双方做好约定校验 super.start( new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>( responseListener) { @Override public void onHeaders(Metadata headers) { super.onHeaders(headers); } }, headers); } }; } }
配置文件
client:
myservice:
# 传输类型,默认是ssl
negotiationType: PLAINTEXT
address: static://127.0.0.1:5012
基本的整合就这样,具体实现的还需要根据具体业务去做一些实现,还有就是一些其他的参数配置,可以根据官网文档,做一些相应的配置。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。