• spring boot 集成 gRPC 系列1


    @[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对应的版本下载


    二、gRPC项目构建

     项目目录结构


    项目结构


    创建maven父工程spring-boot-grpc
    完整pom.xml

    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.     <modelVersion>4.0.0</modelVersion>
    6.     <packaging>pom</packaging>
    7.     <modules>
    8.         <module>spring-boot-grpc-lib</module>
    9.         <module>local-server</module>
    10.         <module>local-client</module>
    11.     </modules>
    12.     <parent>
    13.         <groupId>org.springframework.boot</groupId>
    14.         <artifactId>spring-boot-starter-parent</artifactId>
    15.         <version>2.6.1</version>
    16.         <relativePath/> <!-- lookup parent from repository -->
    17.     </parent>
    18.     <groupId>org.example</groupId>
    19.     <artifactId>spring-boot-grpc</artifactId>
    20.     <version>1.0-SNAPSHOT</version>
    21.     <dependencies>
    22.         <dependency>
    23.             <groupId>org.springframework.boot</groupId>
    24.             <artifactId>spring-boot-starter-web</artifactId>
    25.         </dependency>
    26.         <dependency>
    27.             <groupId>org.springframework.boot</groupId>
    28.             <artifactId>spring-boot-starter-test</artifactId>
    29.             <scope>test</scope>
    30.         </dependency>
    31.     </dependencies>
    32.     <build>
    33.         <plugins>
    34.             <plugin>
    35.                 <groupId>org.apache.maven.plugins</groupId>
    36.                 <artifactId>maven-compiler-plugin</artifactId>
    37.                 <version>3.8.1</version>
    38.                 <configuration>
    39.                     <source>1.8</source>
    40.                     <target>1.8</target>
    41.                     <encoding>UTF-8</encoding>
    42.                 </configuration>
    43.             </plugin>
    44.             <plugin>
    45.                 <groupId>org.springframework.boot</groupId>
    46.                 <artifactId>spring-boot-maven-plugin</artifactId>
    47.                 <version>2.6.1</version>
    48.             </plugin>
    49.         </plugins>
    50.     </build>
    51. </project>


    创建模块spring-boot-grpc-lib
    此模块负责将.proto文件生成Java对应的类与接口

    根据官方文档

    选择对应的版本查看README.md

    可以根据提交历史查看具体proto版本对应的pom.xml

    完整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.     <parent>
    5.         <groupId>org.example</groupId>
    6.         <artifactId>spring-boot-grpc</artifactId>
    7.         <version>1.0-SNAPSHOT</version>
    8.     </parent>
    9.     <modelVersion>4.0.0</modelVersion>
    10.     <groupId>com.example</groupId>
    11.     <artifactId>spring-boot-grpc-lib</artifactId>
    12.     <version>0.0.1-SNAPSHOT</version>
    13.     <name>spring-boot-grpc-lib</name>
    14.     <description>Demo project for Spring Boot</description>
    15.     <properties>
    16.         <java.version>1.8</java.version>
    17.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    18.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    19.     </properties>
    20.     <dependencies>
    21.         <dependency>
    22.             <groupId>io.grpc</groupId>
    23.             <artifactId>grpc-netty-shaded</artifactId>
    24.             <version>1.42.1</version>
    25.         </dependency>
    26.         <dependency>
    27.             <groupId>io.grpc</groupId>
    28.             <artifactId>grpc-protobuf</artifactId>
    29.             <version>1.42.1</version>
    30.         </dependency>
    31.         <dependency>
    32.             <groupId>io.grpc</groupId>
    33.             <artifactId>grpc-stub</artifactId>
    34.             <version>1.42.1</version>
    35.         </dependency>
    36.         <dependency> <!-- necessary for Java 9+ -->
    37.             <groupId>org.apache.tomcat</groupId>
    38.             <artifactId>annotations-api</artifactId>
    39.             <version>6.0.53</version>
    40.             <scope>provided</scope>
    41.         </dependency>
    42.         <dependency>
    43.             <groupId>com.google.protobuf</groupId>
    44.             <artifactId>protobuf-java</artifactId>
    45.             <version>3.17.2</version>
    46.         </dependency>
    47.         <dependency>
    48.             <groupId>com.google.protobuf</groupId>
    49.             <artifactId>protobuf-java-util</artifactId>
    50.             <version>3.17.2</version>
    51.         </dependency>
    52.         <dependency>
    53.             <groupId>javax.annotation</groupId>
    54.             <artifactId>javax.annotation-api</artifactId>
    55.             <version>1.3.2</version>
    56.         </dependency>
    57.     </dependencies>
    58.     <dependencyManagement>
    59.         <dependencies>
    60.             <dependency>
    61.                 <groupId>io.grpc</groupId>
    62.                 <artifactId>grpc-bom</artifactId>
    63.                 <version>1.42.2</version>
    64.                 <type>pom</type>
    65.                 <scope>import</scope>
    66.             </dependency>
    67.         </dependencies>
    68.     </dependencyManagement>
    69.     <build>
    70.         <extensions>
    71.             <extension>
    72.                 <groupId>kr.motd.maven</groupId>
    73.                 <artifactId>os-maven-plugin</artifactId>
    74.                 <version>1.6.2</version>
    75.             </extension>
    76.         </extensions>
    77.         <plugins>
    78.             <plugin>
    79.                 <groupId>org.xolstice.maven.plugins</groupId>
    80.                 <artifactId>protobuf-maven-plugin</artifactId>
    81.                 <version>0.6.1</version>
    82.                 <configuration>
    83.                     <protocArtifact>com.google.protobuf:protoc:3.17.2:exe:${os.detected.classifier}</protocArtifact>
    84.                     <pluginId>grpc-java</pluginId>
    85.                     <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.42.1:exe:${os.detected.classifier}</pluginArtifact>
    86.                 </configuration>
    87.                 <executions>
    88.                     <execution>
    89.                         <goals>
    90.                             <goal>compile</goal>
    91.                             <goal>compile-custom</goal>
    92.                         </goals>
    93.                     </execution>
    94.                 </executions>
    95.             </plugin>
    96.         </plugins>
    97.     </build>
    98. </project>



    创建proto文件

    在spring-boot-grpc-lib模块的src/main/proto目录下新增名为helloworld.proto的文件

    这里面定义了一个gRPC服务,里面含有一个接口,并且还有这个接口的入参和返回结果的定义

    proto文件夹需要在 File -> ProjectStructure 中将其标记为sources


    helloworld.proto完整代码

    1. syntax = "proto3"; // 协议版本
    2. // 选项配置
    3. option java_multiple_files = true;
    4. option java_package = "com.example.springbootgrpclib.grpc.protobuf";
    5. option java_outer_classname = "SimpleProto";
    6. service Simple {
    7.     // 简单gRPC
    8.     rpc OneToOne (MyRequest) returns (MyResponse) {
    9.     }
    10. }
    11. message MyRequest {
    12.     string name = 1;
    13.     int32 value = 2;
    14. }
    15. message MyResponse {
    16.     string message = 1;
    17.     int64 result = 2;
    18. }


    生成Java类

    idea 单击编译类

    生成对应的类并且将其复制到spring-boot-grpc-lib下

    spring-boot-grpc-lib结构:

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


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

    添加gRPC 服务端 Maven 依赖和spring-boot-grpc-lib模块

    完整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.         <groupId>org.example</groupId>
    7.         <artifactId>spring-boot-grpc</artifactId>
    8.         <version>1.0-SNAPSHOT</version>
    9.     </parent>
    10.     <groupId>com.example</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>11</java.version>
    17.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    18.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    19.         <spring-boot.version>2.6.1</spring-boot.version>
    20.     </properties>
    21.     <dependencies>
    22.         <!--Lombok引入-->
    23.         <dependency>
    24.             <groupId>org.projectlombok</groupId>
    25.             <artifactId>lombok</artifactId>
    26.             <optional>true</optional>
    27.         </dependency>
    28.         <!--gRPC服务端-->
    29.         <dependency>
    30.             <groupId>net.devh</groupId>
    31.             <artifactId>grpc-server-spring-boot-starter</artifactId>
    32.             <version>2.13.0.RELEASE</version>
    33.         </dependency>
    34.         <!--spring-boot-grpc-lib模块-->
    35.         <dependency>
    36.             <groupId>com.example</groupId>
    37.             <artifactId>spring-boot-grpc-lib</artifactId>
    38.             <version>0.0.1-SNAPSHOT</version>
    39.         </dependency>
    40.     </dependencies>
    41. </project>


    springboot配置文件 application.yml

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

    增加启动类RpcServerApplication

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


    在service类中将gRPC服务对外暴露出去

    完整代码如下

    1. package com.example.localserver.server;
    2. import com.example.springbootgrpclib.grpc.protobuf.MyRequest;
    3. import com.example.springbootgrpclib.grpc.protobuf.MyResponse;
    4. import com.example.springbootgrpclib.grpc.protobuf.SimpleGrpc;
    5. import io.grpc.stub.StreamObserver;
    6. import lombok.extern.slf4j.Slf4j;
    7. import net.devh.boot.grpc.server.service.GrpcService;
    8. @GrpcService
    9. @Slf4j
    10. public class GrpcServerService extends SimpleGrpc.SimpleImplBase {
    11.     @Override
    12.     public void oneToOne(MyRequest request, StreamObserver<MyResponse> responseObserver) {
    13.         log.info("接收客户端数据{}", request);
    14.         MyResponse response = MyResponse.newBuilder().setMessage( request.getName()).build();
    15.         responseObserver.onNext(response);
    16.         responseObserver.onCompleted();
    17.     }
    18.     
    19. }



    上述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服务端编码就完成了,服务端流、客户端流和双向流在后面介绍。

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


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

    添加gRPC客户端 Maven 依赖和spring-boot-grpc-lib模块

    完整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.         <groupId>org.example</groupId>
    7.         <artifactId>spring-boot-grpc</artifactId>
    8.         <version>1.0-SNAPSHOT</version>
    9.     </parent>
    10.     <groupId>com.example</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>11</java.version>
    17.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    18.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    19.         <spring-boot.version>2.6.1</spring-boot.version>
    20.     </properties>
    21.     <dependencies>
    22.         
    23.         <!--gRPC客户端-->
    24.         <dependency>
    25.             <groupId>net.devh</groupId>
    26.             <artifactId>grpc-client-spring-boot-starter</artifactId>
    27.             <version>2.13.0.RELEASE</version>
    28.         </dependency>
    29.         <!--spring-boot-grpc-lib模块-->
    30.         <dependency>
    31.             <groupId>com.example</groupId>
    32.             <artifactId>spring-boot-grpc-lib</artifactId>
    33.             <version>0.0.1-SNAPSHOT</version>
    34.         </dependency>
    35.         <!--lombok-->
    36.         <dependency>
    37.             <groupId>org.projectlombok</groupId>
    38.             <artifactId>lombok</artifactId>
    39.             <optional>true</optional>
    40.         </dependency>
    41.     </dependencies>
    42. </project>


    springboot配置文件 application.yml:

    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

    启动类RpcClientApplication

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



    服务类GrpcClientService

    1. package com.example.localclient.service;
    2. import com.example.springbootgrpclib.grpc.protobuf.MyRequest;
    3. import com.example.springbootgrpclib.grpc.protobuf.MyResponse;
    4. import com.example.springbootgrpclib.grpc.protobuf.SimpleGrpc;
    5. import io.grpc.StatusRuntimeException;
    6. import lombok.extern.slf4j.Slf4j;
    7. import net.devh.boot.grpc.client.inject.GrpcClient;
    8. import org.springframework.stereotype.Service;
    9. @Service
    10. @Slf4j
    11. public class GrpcClientService {
    12.     @GrpcClient("local-grpc-server")
    13.     private SimpleGrpc.SimpleBlockingStub simpleStub;
    14.     public String oneToOne(final String name) {
    15.         try {
    16.             final MyResponse response = this.simpleStub.oneToOne(MyRequest.newBuilder().setName(name).build());
    17.             return response.getMessage();
    18.         } catch (final StatusRuntimeException e) {
    19.             return "FAILED with " + e.getStatus().getCode().name();
    20.         }
    21.     }
    22. }



    上述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服务调用能否成功

    1. package com.example.localclient.controller;
    2. import com.example.localclient.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. import java.util.List;
    8. /**
    9.  * @author cdj
    10.  * @date 2022/4/11 - 17:36
    11.  **/
    12. @RestController
    13. public class GrpcClientController {
    14.     @Autowired
    15.     private GrpcClientService grpcClientService;
    16.     @RequestMapping("/oneToOne")
    17.     public String oneToOne(@RequestParam(defaultValue = "name") String name) {
    18.         return grpcClientService.oneToOne(name);
    19.     }
    20. }

    调用效果

    http://127.0.0.1:8088/oneToOne?name=rpc-test

  • 相关阅读:
    mybatis单框架实现数据库新增、删除、修改
    flowable-ui部署
    LeetCode50天刷题计划第二季(Day 17 — 克隆图 (10.00-11.20)
    加油站智能视频监控系统
    A1052 Linked List Sorting(25分)PAT 甲级(Advanced Level) Practice(C++)满分题解【链表地址+排序]
    解决npm报错Error: error:0308010C:digital envelope routines::unsupported
    花房集团赴港IPO:直播与社交双引擎驱动,构筑元宇宙生态迈入“以用户为核心”向阳路
    夜天之书 #67 为什么开源协议不授予商标权利?
    Hash的底层结构
    从0搭建Vue3组件库(二):Monorepo项目搭建
  • 原文地址:https://blog.csdn.net/rdhj5566/article/details/125407910