1.前言 在java和python通信章节里面,我写了如何使用java开发grpc的客户端和服务端。但是在springboot里面,要是同时使用 springboot 和 grpc 服务,似乎不行。因为 awaitTermination 会阻塞程序运行,如下代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 @Component public class AiServer extends ManageAiGrpc .ManageAiImplBase { @Value("${grpc.localport}") private int localport; @Override public void addManageAi (ManageAiRequest request, StreamObserver<ManageAiResponse> responseObserver) { ManageAiResponse response = ManageAiResponse.newBuilder() .setCode(200 ) .setSuccess(true ) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } @PostConstruct public void initServer () { try { Server server = ServerBuilder.forPort(localport) .addService(new AiServer ()) .build(); server.start(); log.info("Grpc Server started" ); server.awaitTermination(); }catch (Exception e){ log.error(e.getMessage(), e); } } }
参考文章:
【1】.
springboot项目同时启动web服务和grpc服务 引入spring-boot-starter-web依赖和grpc-client-spring-boot-starter依赖
【2】.
手把手带你写一个SpringBoot + gRPC服务 这里用了 org.lognet 的 grpc-spring-boot-starter,创建了一个服务器,创建一个HelloWorldClient类,实例化stub对象,并发送rpc请求的方法,这个没有用 @GrpClient 的地方。
【3】.
使用注解@GrpcService在Spring Boot 中开始使用gRPC 在使用Spring Boot构建独立、生产级基于Spring的应用程序的广泛框架时,通过使用注解简化了将gRPC集成到应用程序中的步骤。@GrpcService注解是gRPC Spring Boot启动器库的一部分,提供了gRPC和Spring Boot之间的无缝集成。它允许开发人员在Spring Boot应用程序中轻松定义gRPC服务,自动处理大部分样板代码和配置。
2.添加依赖 我的是 spring boot 3.1.x版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 <dependencies > <dependency > <groupId > io.grpc</groupId > <artifactId > grpc-netty-shaded</artifactId > <version > 1.58.0</version > </dependency > <dependency > <groupId > io.grpc</groupId > <artifactId > grpc-protobuf</artifactId > <version > 1.58.0</version > </dependency > <dependency > <groupId > io.grpc</groupId > <artifactId > grpc-stub</artifactId > <version > 1.58.0</version > </dependency > <dependency > <groupId > net.devh</groupId > <artifactId > grpc-spring-boot-starter</artifactId > <version > 2.15.0.RELEASE</version > </dependency > </dependencies > <build > <resources > <resource > <directory > ${project.basedir}/src/main/resources</directory > </resource > <resource > <directory > ${project.basedir}/src/main/java</directory > <includes > <include > **/*.xml</include > <include > **/*.json</include > <include > **/*.html</include > </includes > </resource > </resources > <extensions > <extension > <groupId > kr.motd.maven</groupId > <artifactId > os-maven-plugin</artifactId > <version > 1.6.2</version > </extension > </extensions > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <configuration > <source > 16</source > <target > 16</target > </configuration > </plugin > <plugin > <groupId > org.xolstice.maven.plugins</groupId > <artifactId > protobuf-maven-plugin</artifactId > <version > 0.5.0</version > <configuration > <protoSourceRoot > src/main/proto</protoSourceRoot > <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 > <clearOutputDirectory > true</clearOutputDirectory > </configuration > <executions > <execution > <goals > <goal > compile</goal > <goal > compile-custom</goal > </goals > </execution > </executions > </plugin > </plugins > </build >
参考文章:
【1】.
Spring Boot下grpc最佳实践 通过教程中例子,你可以学会以下技能:如何定义服务接口、如何生成服务器和客户端代码、如何集成spring boot 实现一个简单的客户端和服务器。
3.修改启动类 这一步非常的重要,否则就会报错,主要就是增加了 @ImportAutoConfiguration 注解,添加了 grpc 的相关配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @Slf4j @SpringBootApplication @ImportAutoConfiguration({ JustAuthAutoConfiguration.class, net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration.class, net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration.class }) @ComponentScan(basePackages = {"com.dji.*","org.jeecg.*"}) @MapperScan(basePackages = {"com.dji.sample.*.dao","com.dji.sample.drone.mapper"}) @EnableScheduling public class JeecgSystemApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure (SpringApplicationBuilder application) { return application.sources(JeecgSystemApplication.class); } public static void main (String[] args) throws UnknownHostException { ConfigurableApplicationContext application = SpringApplication.run(JeecgSystemApplication.class, args); Environment env = application.getEnvironment(); String ip = InetAddress.getLocalHost().getHostAddress(); String port = env.getProperty("server.port" ); String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path" )); } }
2.客户端 (1)编写配置文件 这个 grpc-server 是服务的名字,可以自定义。
1 2 3 4 5 6 7 8 9 10 grpc: client: grpc-ai: address: static://localhost:50052 negotiation-type: plaintext enableKeepAlive: true keepAliveTime: 30s keepAliveTimeout: 5s
(2) 使用 @GrpcClient Sub在第一步使用proto生成的时候,已经有了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @GrpcClient("grpc-ai") private AiGrpc.AiBlockingStub blockingStub;public AiReply start (String sn,String videoid) { AiLiveRequest request = AiLiveRequest.newBuilder().setSn(sn).setVideoid(videoid).build(); AiReply response; try { response = blockingStub.start(request); return response; } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}" , e.getStatus()); } return AiReply.newBuilder().build(); }
3.服务端 (1) 编写配置
1 2 3 4 5 grpc: server: port: 9999 security: enabled: false
(2) 实现服务 在需要的类上增加 @GrpcService 就可以启动一个 grpc 的server服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 @Slf4j @Component @GrpcService public class AiServer extends ManageAiGrpc .ManageAiImplBase { @Override public StreamObserver<FileUploadRequest> fileUpload (StreamObserver<ManageAiResponse> responseObserver) { return new StreamObserver <FileUploadRequest>() { @Override public void onNext (FileUploadRequest stock) { log.info(stock.toString()); } @Override public void onCompleted () { responseObserver.onNext(ManageAiResponse.newBuilder() .setCode(200 ) .setSuccess(true ) .build()); responseObserver.onCompleted(); } @Override public void onError (Throwable t) { log.error(t.getMessage(), t); } }; } @Override public void addManageAi (ManageAiRequest request, StreamObserver<ManageAiResponse> responseObserver) { ManageAiResponse response = ManageAiResponse.newBuilder() .setCode(200 ) .setSuccess(true ) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } }
参考文章:
【1】.
在SpringBoot中集成grpc-server-spring-boot-starter实现gRPC服务 这里我们使用的spring-boot版本与grpc-client-spring-boot-starter和grpc-server-spring-boot-starter使用的版本不同,所以后面我们需要在grpc的starter排除掉默认的spring-boot版本。
【2】.
使用 @GrpcClient 实现客户端 使用 @GrpcClient 注解的场景通常是在 Spring Boot 中使用 gRPC 客户端时,因为 Spring Boot 已经为我们提供了自动配置功能,可以简化 gRPC 客户端的配置和使用。在这种场景下,我们只需要在应用程序中添加 @GrpcClient 注解,然后在配置文件中添加 gRPC 客户端的配置信息,就可以方便地使用 gRPC 客户端了。
【3】.
Spring Tips: GRPC 这个就是一个视频,好像是官方的说明,但是我用的总是不太好看。
【4】.
配置 本节描述您如何配置您的 grpc-spring-boot-starter 客户端。
【5】.
手把手教你把gRPC集成到SpringBoot3框架中 增加@ImportAutoConfiguration内容,让SpringBoot3识别启动gRPC服务器。这里解决了我在 springboot 3.x.x 的框架中增加 grpc 的问题,解决了我的问题。
问题 1.micrometer-core不兼容 在使用 3.1.0 版本的时候,出现了这个问题,The following method did not exist,’io.micrometer.core.instrument.Meter$MeterProvider io.micrometer.core.instrument.Counter$Builder.withRegistry(io.micrometer.core.instrument.MeterRegistry)’
【解决方案】 主要的解决方案就是降低 版本,从 3.1.0.RELEASE,降到了 2.15.0.RELEASE
1 2 3 4 5 <dependency > <groupId > net.devh</groupId > <artifactId > grpc-spring-boot-starter</artifactId > <version > 2.15.0.RELEASE</version > </dependency >
2.Error creating bean with name ‘grpcChannelHealthIndicator’ defined in class path resource 解决了版本问题,然后启动之后,出现了新的问题,好像启动不了。 “Factory method ‘shadedNettyGrpcChannelFactory’ threw exception with message: io/grpc/internal/AbstractManagedChannelImplBuilder。” “Unsatisfied dependency expressed through method ‘grpcChannelHealthIndicator’ parameter 0”
【尝试方案】 (1) 增加了 grpc-server-spring-boot-autoconfigure 依赖,无效。
1 2 3 4 5 <dependency > <groupId > net.devh</groupId > <artifactId > grpc-server-spring-boot-autoconfigure</artifactId > <version > 2.15.0.RELEASE</version > </dependency >
(2)排除 grpc-netty-shaded 无效。
1 2 3 4 5 6 7 8 9 10 11 <dependency > <groupId > net.devh</groupId > <artifactId > grpc-spring-boot-starter</artifactId > <version > 2.15.0.RELEASE</version > <exclusions > <exclusion > <groupId > io.grpc</groupId > <artifactId > grpc-netty-shaded</artifactId > </exclusion > </exclusions > </dependency >
【解决方案】 最后的解决方案就是在启动类上增加
1 2 3 4 5 6 7 8 9 10 11 12 13 @ImportAutoConfiguration({ JustAuthAutoConfiguration.class, net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration.class, net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration.class, net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration.class })