当前位置:   article > 正文

使用spring boot集成grpc_springboot grpc集成

springboot grpc集成

目录

创建maven父工程spring-boot-grpc

创建模块spring-boot-grpc-lib

创建模块local-server(gRPC服务端)

创建模块local-client(gRPC客户端)


创建maven父工程spring-boot-grpc

创建springboot项目,勾选springboot-web即可

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <packaging>pom</packaging>
  6. <modules>
  7. <module>spring-boot-grpc-lib</module>
  8. <module>local-server</module>
  9. <module>local-client</module>
  10. </modules>
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>2.5.6</version>
  15. <relativePath/> <!-- lookup parent from repository -->
  16. </parent>
  17. <groupId>com.chenj</groupId>
  18. <artifactId>spring-boot-grpc</artifactId>
  19. <version>0.0.1-SNAPSHOT</version>
  20. <name>spring-boot-grpc</name>
  21. <description>Demo project for Spring Boot</description>
  22. <properties>
  23. <java.version>1.8</java.version>
  24. </properties>
  25. <dependencies>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-web</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-test</artifactId>
  33. <scope>test</scope>
  34. </dependency>
  35. </dependencies>
  36. <!-- <build>
  37. <plugins>
  38. <plugin>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-maven-plugin</artifactId>
  41. </plugin>
  42. </plugins>
  43. </build>-->
  44. </project>

创建模块spring-boot-grpc-lib

在父工程spring-boot-grpc下新建maven模块,名为spring-boot-grpc-lib

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>spring-boot-grpc</artifactId>
  7. <groupId>com.chenj</groupId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>spring-boot-grpc-lib</artifactId>
  12. <properties>
  13. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  14. <maven.compiler.source>1.8</maven.compiler.source>
  15. <maven.compiler.target>1.8</maven.compiler.target>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>io.grpc</groupId>
  20. <artifactId>grpc-netty-shaded</artifactId>
  21. <version>1.37.0</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>io.grpc</groupId>
  25. <artifactId>grpc-protobuf</artifactId>
  26. <version>1.37.0</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>io.grpc</groupId>
  30. <artifactId>grpc-stub</artifactId>
  31. <version>1.37.0</version>
  32. </dependency>
  33. <dependency> <!-- necessary for Java 9+ -->
  34. <groupId>org.apache.tomcat</groupId>
  35. <artifactId>annotations-api</artifactId>
  36. <version>6.0.53</version>
  37. <scope>provided</scope>
  38. </dependency>
  39. </dependencies>
  40. <build>
  41. <extensions>
  42. <extension>
  43. <groupId>kr.motd.maven</groupId>
  44. <artifactId>os-maven-plugin</artifactId>
  45. <version>1.6.2</version>
  46. </extension>
  47. </extensions>
  48. <plugins>
  49. <plugin>
  50. <groupId>org.xolstice.maven.plugins</groupId>
  51. <artifactId>protobuf-maven-plugin</artifactId>
  52. <version>0.6.1</version>
  53. <configuration>
  54. <protocArtifact>com.google.protobuf:protoc:3.17.3:exe:${os.detected.classifier}</protocArtifact>
  55. <pluginId>grpc-java</pluginId>
  56. <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.37.0:exe:${os.detected.classifier}</pluginArtifact>
  57. </configuration>
  58. <executions>
  59. <execution>
  60. <goals>
  61. <goal>compile</goal>
  62. <goal>compile-custom</goal>
  63. </goals>
  64. </execution>
  65. </executions>
  66. </plugin>
  67. </plugins>
  68. </build>
  69. </project>

在spring-boot-grpc-lib模块的src/main/proto目录下新增名为helloworld.proto的文件,这里面定义了一个gRPC服务,里面含有一个接口,并且还有这个接口的入参和返回结果的定义:

  1. syntax = "proto3";
  2. option java_multiple_files = true;
  3. option java_package = "com.chenj.grpc.lib";
  4. option java_outer_classname = "HelloWorldProto";
  5. // The greeting service definition.
  6. service Simple {
  7. // Sends a greeting
  8. rpc SayHello (HelloRequest) returns (HelloReply) {
  9. }
  10. }
  11. // The request message containing the user's name.
  12. message HelloRequest {
  13. string name = 1;
  14. }
  15. // The response message containing the greetings
  16. message HelloReply {
  17. string message = 1;
  18. }

proto文件已经做好,接下来要根据这个文件来生成Java代码

SimpleGrpc里面有抽象类SimpleImplBase,制作gRPC服务的时候需要继承该类,另外,如果您要远程调用gRPC的sayHello接口,就会用到SimpleGrpc类中的SimpleStub类,其余的HelloReply、HelloRequest这些则是入参和返回的数据结构定义

创建模块local-server(gRPC服务端)

在父工程下面新建名为local-server的springboot模块,

gRPC 服务端使用一下命令添加 Maven 依赖项

  1. <dependency>
  2. <groupId>net.devh</groupId>
  3. <artifactId>grpc-server-spring-boot-starter</artifactId>
  4. <version>2.12.0.RELEASE</version>
  5. </dependency>

依赖上面的spring-boot-grpc-lib模块

  1. <dependency>
  2. <groupId>com.chenj</groupId>
  3. <artifactId>spring-boot-grpc-lib</artifactId>
  4. <version>0.0.1-SNAPSHOT</version>
  5. </dependency>

完整的pom.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <artifactId>spring-boot-grpc</artifactId>
  7. <groupId>com.chenj</groupId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <groupId>com.chenj</groupId>
  11. <artifactId>local-server</artifactId>
  12. <version>0.0.1-SNAPSHOT</version>
  13. <name>local-server</name>
  14. <description>Demo project for Spring Boot</description>
  15. <properties>
  16. <java.version>1.8</java.version>
  17. </properties>
  18. <dependencies>
  19. <dependency>
  20. <groupId>net.devh</groupId>
  21. <artifactId>grpc-server-spring-boot-starter</artifactId>
  22. <version>2.12.0.RELEASE</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>com.chenj</groupId>
  26. <artifactId>spring-boot-grpc-lib</artifactId>
  27. <version>0.0.1-SNAPSHOT</version>
  28. </dependency>
  29. <!--Lombok引入-->
  30. <dependency>
  31. <groupId>org.projectlombok</groupId>
  32. <artifactId>lombok</artifactId>
  33. </dependency>
  34. </dependencies>
  35. <!--<build>
  36. <plugins>
  37. <plugin>
  38. <groupId>org.springframework.boot</groupId>
  39. <artifactId>spring-boot-maven-plugin</artifactId>
  40. </plugin>
  41. </plugins>
  42. </build>-->
  43. </project>

springboot应用,配置文件内容如下:

  1. spring:
  2. application:
  3. name: spring-boot-grpc-server
  4. # gRPC有关的配置,这里只需要配置服务端口号
  5. grpc:
  6. server:
  7. port: 9898
  8. server:
  9. port: 8080

新建拦截类LogGrpcInterceptor.java,每当gRPC请求到来后该类会先执行,这里是将方法名字在日志中打印出来,您可以对请求响应做更详细的处理:

  1. package com.chenj.springbootgrpcserver.interceptor;
  2. import io.grpc.Metadata;
  3. import io.grpc.ServerCall;
  4. import io.grpc.ServerCallHandler;
  5. import io.grpc.ServerInterceptor;
  6. import lombok.extern.slf4j.Slf4j;
  7. @Slf4j
  8. public class LogGrpcInterceptor implements ServerInterceptor {
  9. @Override
  10. public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,
  11. ServerCallHandler<ReqT, RespT> serverCallHandler) {
  12. log.info(serverCall.getMethodDescriptor().getFullMethodName());
  13. return serverCallHandler.startCall(serverCall, metadata);
  14. }
  15. }

为了让LogGrpcInterceptor可以在gRPC请求到来时被执行,需要做相应的配置,如下所示,在普通的bean的配置中添加注解即可:

  1. package com.chenj.springbootgrpcserver.config;
  2. import com.chenj.springbootgrpcserver.interceptor.LogGrpcInterceptor;
  3. import io.grpc.ServerInterceptor;
  4. import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration(proxyBeanMethods = false)
  7. public class GlobalInterceptorConfiguration {
  8. @GrpcGlobalServerInterceptor
  9. ServerInterceptor logServerInterceptor() {
  10. return new LogGrpcInterceptor();
  11. }
  12. }

应用启动类很简单:

  1. package com.chenj.springbootgrpcserver;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class SpringBootGrpcServerApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run(SpringBootGrpcServerApplication.class, args);
  8. }
  9. }

接下来是最重要的service类,gRPC服务在此处对外暴露出去,完整代码如下

  1. package com.chenj.springbootgrpcserver.service;
  2. import com.chenj.grpc.lib.HelloReply;
  3. import com.chenj.grpc.lib.HelloRequest;
  4. import com.chenj.grpc.lib.SimpleGrpc;
  5. import io.grpc.stub.StreamObserver;
  6. import net.devh.boot.grpc.server.service.GrpcService;
  7. import java.util.Date;
  8. @GrpcService
  9. public class GrpcServerService extends SimpleGrpc.SimpleImplBase {
  10. @Override
  11. public void sayHello(HelloRequest request,
  12. StreamObserver<HelloReply> responseObserver) {
  13. HelloReply reply = HelloReply.newBuilder().setMessage("你好, " + request.getName() + ", " + new Date()).build();
  14. responseObserver.onNext(reply);
  15. responseObserver.onCompleted();
  16. }
  17. }

上述GrpcServerService.java中有几处需要注意:

是使用@GrpcService注解,再继承SimpleImplBase,这样就可以借助grpc-server-spring-boot-starter库将sayHello暴露为gRPC服务;

SimpleImplBase是前文中根据proto自动生成的java代码,在spring-boot-grpc-lib模块中;

sayHello方法中处理完毕业务逻辑后,调用HelloReply.onNext方法填入返回内容;

调用HelloReply.onCompleted方法表示本次gRPC服务完成;

至此,gRPC服务端编码就完成了,咱们接着开始客户端开发

创建模块local-client(gRPC客户端)

在父工程grpc-turtorials下面新建名为local-client的模块

gRPC客户端使用一下命令添加 Maven 依赖项:

  1. <dependency>
  2. <groupId>net.devh</groupId>
  3. <artifactId>grpc-client-spring-boot-starter</artifactId>
  4. <version>2.12.0.RELEASE</version>
  5. </dependency>

依赖上面的spring-boot-grpc-lib模块

  1. <dependency>
  2. <groupId>com.chenj</groupId>
  3. <artifactId>spring-boot-grpc-lib</artifactId>
  4. <version>0.0.1-SNAPSHOT</version>
  5. </dependency>

完整的pom.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <artifactId>spring-boot-grpc</artifactId>
  7. <groupId>com.chenj</groupId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. </parent>
  10. <groupId>com.chenj</groupId>
  11. <artifactId>local-client</artifactId>
  12. <version>0.0.1-SNAPSHOT</version>
  13. <name>local-client</name>
  14. <description>Demo project for Spring Boot</description>
  15. <properties>
  16. <java.version>1.8</java.version>
  17. </properties>
  18. <dependencies>
  19. <dependency>
  20. <groupId>net.devh</groupId>
  21. <artifactId>grpc-client-spring-boot-starter</artifactId>
  22. <version>2.12.0.RELEASE</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>com.chenj</groupId>
  26. <artifactId>spring-boot-grpc-lib</artifactId>
  27. <version>0.0.1-SNAPSHOT</version>
  28. </dependency>
  29. </dependencies>
  30. <build>
  31. <plugins>
  32. <plugin>
  33. <groupId>org.springframework.boot</groupId>
  34. <artifactId>spring-boot-maven-plugin</artifactId>
  35. </plugin>
  36. </plugins>
  37. </build>
  38. </project>

应用配置文件src/main/resources/application.yml,注意address的值就是gRPC服务端的信息,我这里local-server和local-client在同一台电脑上运行,请您根据自己情况来设置:

  1. server:
  2. port: 8088
  3. spring:
  4. application:
  5. name: local-client
  6. grpc:
  7. client:
  8. # gRPC配置的名字,GrpcClient注解会用到
  9. local-grpc-server:
  10. # gRPC服务端地址
  11. address: 'static://127.0.0.1:9898'
  12. enableKeepAlive: true
  13. keepAliveWithoutCalls: true
  14. negotiationType: plaintext

新建拦截类LogGrpcInterceptor,与服务端的拦截类差不多,不过实现的接口不同:

  1. package com.chenj.springbootgrpcclient.interceptor;
  2. import io.grpc.*;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. public class LogGrpcInterceptor implements ClientInterceptor {
  6. private static final Logger log = LoggerFactory.getLogger(LogGrpcInterceptor.class);
  7. @Override
  8. public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
  9. CallOptions callOptions, Channel next) {
  10. log.info(method.getFullMethodName());
  11. return next.newCall(method, callOptions);
  12. }
  13. }

为了让拦截类能够正常工作,即发起gRPC请求的时候被执行,需要新增一个配置类:

  1. package com.chenj.springbootgrpcclient.config;
  2. import com.chenj.springbootgrpcclient.interceptor.LogGrpcInterceptor;
  3. import io.grpc.ClientInterceptor;
  4. import net.devh.boot.grpc.client.interceptor.GrpcGlobalClientInterceptor;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.core.Ordered;
  7. import org.springframework.core.annotation.Order;
  8. @Order(Ordered.LOWEST_PRECEDENCE)
  9. @Configuration(proxyBeanMethods = false)
  10. public class GlobalClientInterceptorConfiguration {
  11. @GrpcGlobalClientInterceptor
  12. ClientInterceptor logClientInterceptor() {
  13. return new LogGrpcInterceptor();
  14. }
  15. }

启动类:

  1. package com.chenj.springbootgrpcclient;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class SpringBootGrpcClientApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run(SpringBootGrpcClientApplication.class, args);
  8. }
  9. }

接下来是最重要的服务类GrpcClientService

  1. package com.chenj.springbootgrpcclient.service;
  2. import com.chenj.grpc.lib.HelloReply;
  3. import com.chenj.grpc.lib.HelloRequest;
  4. import com.chenj.grpc.lib.SimpleGrpc;
  5. import io.grpc.StatusRuntimeException;
  6. import net.devh.boot.grpc.client.inject.GrpcClient;
  7. import org.springframework.stereotype.Service;
  8. @Service
  9. public class GrpcClientService {
  10. @GrpcClient("local-grpc-server")
  11. private SimpleGrpc.SimpleBlockingStub simpleStub;
  12. public String sendMessage(final String name) {
  13. try {
  14. final HelloReply response = this.simpleStub.sayHello(HelloRequest.newBuilder().setName(name).build());
  15. return response.getMessage();
  16. } catch (final StatusRuntimeException e) {
  17. return "FAILED with " + e.getStatus().getCode().name();
  18. }
  19. }
  20. }

上述GrpcClientService类有几处要注意的地方:

用@Service将GrpcClientService注册为spring的普通bean实例;

用@GrpcClient修饰SimpleBlockingStub,这样就可以通过grpc-client-spring-boot-starter库发起gRPC调用,被调用的服务端信息来自名为local-grpc-server的配置;

SimpleBlockingStub来自前文中根据helloworld.proto生成的java代码;

SimpleBlockingStub.sayHello方法会远程调用local-server应用的gRPC服务;

为了验证gRPC服务调用能否成功,再新增个web接口,接口内部会调用GrpcClientService.sendMessage,这样咱们通过浏览器就能验证gRPC服务是否调用成功了:

  1. package com.chenj.springbootgrpcclient.controller;
  2. import com.chenj.springbootgrpcclient.service.GrpcClientService;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestParam;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @RestController
  8. public class GrpcClientController {
  9. @Autowired
  10. private GrpcClientService grpcClientService;
  11. @RequestMapping("/")
  12. public String printMessage(@RequestParam(defaultValue = "will") String name) {
  13. return grpcClientService.sendMessage(name);
  14. }
  15. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/128702
推荐阅读
相关标签
  

闽ICP备14008679号