手把手带你写一个SpringBoot + gRPC服务

请注意,本文不会对gRPC基础概念进行解释,而是着重介绍服务的搭建过程。如果你是零基础的伙伴,请先自行学习gRPC的基础知识。接下来,让我们在本地环境下搭建gRPC客户端和服务端,并成功建立通讯发送消息的方式,来学习gRPC在Spring Boot项目中的应用。

客户端(发送rpc请求)

1、导入maven依赖

包含rpc所使用的依赖和构建protobuf的插件。完整的<dependencies><build>如下:

xml 复制代码
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty-shaded</artifactId>
    <version>1.59.1</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-protobuf</artifactId>
    <version>1.59.1</version>
  </dependency>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-stub</artifactId>
    <version>1.59.1</version>
  </dependency>
  <dependency> <!-- necessary for Java 9+ -->
    <groupId>org.apache.tomcat</groupId>
    <artifactId>annotations-api</artifactId>
    <version>6.0.53</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.7.1</version>
    </extension>
  </extensions>
  <plugins>
    <plugin>
      <groupId>org.xolstice.maven.plugins</groupId>
      <artifactId>protobuf-maven-plugin</artifactId>
      <version>0.6.1</version>
      <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.24.0:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.59.1:exe:${os.detected.classifier}</pluginArtifact>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>compile-custom</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

导入成功后,可以在maven的插件中看到protobuf选项;

2、编写Proto文件

在main目录下创建proto软件包,将编写好的Proto文件放在该目录(src/main/proto)下。示例Proto文件内容如下

protobuf 复制代码
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.example.server";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package com.example.server;


service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

完成Proto文件编写后,执行mvn install命令。你会在target/generated-sources/protobuf路径下看到gRPC编译生成的Java代码。这些生成的代码是实现gRPC在不同语言间进行RPC通讯的基础。

3、编写客户端代码

创建一个HelloWorldClient类,实例化stub对象,并发送rpc请求的方法;

java 复制代码
@Service
public class HelloWorldClient {

    private GreeterGrpc.GreeterBlockingStub stub;

    @Value("${grpc.hello-world.host}")
    private String host;
    @Value("${grpc.hello-world.port}")
    private Integer port;

    @PostConstruct
    void init() {
        ManagedChannel channel =
        ManagedChannelBuilder.forAddress(host, port)
        .keepAliveWithoutCalls(true)
        .keepAliveTime(60, TimeUnit.SECONDS)
        .keepAliveTimeout(3, TimeUnit.SECONDS)
        .idleTimeout(60, TimeUnit.SECONDS)
        .maxInboundMessageSize(Integer.MAX_VALUE)
        .usePlaintext().build();
        stub = GreeterGrpc.newBlockingStub(channel);
    }

    /**
     * 说"你好"
     *
     * @param name 名字
     * @return {@link String}
     */
    public String sayHello(String name) {

        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply helloReply = stub.sayHello(request);
        return helloReply.getMessage();
    }
}

这里我配置的gRPC服务端地址如下,请根据实际情况修改host和port的值。

yaml 复制代码
grpc:
  hello-world:
    host: 127.0.0.1
    port: 6565

接下来,让我们继续开发服务端的代码。

服务端(处理rpc请求并返回处理数据)

1、导入maven依赖

与客户端依赖略有不同,服务端中我们使用了grpc-spring-boot-starter

xml 复制代码
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-protobuf</artifactId>
    <version>1.53.0</version>
  </dependency>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-stub</artifactId>
    <version>1.53.0</version>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>
  <dependency>
    <groupId>org.lognet</groupId>
    <artifactId>grpc-spring-boot-starter</artifactId>
    <version>2.3.2</version>
  </dependency>


</dependencies>

<!-- 添加protobuf-maven-plugin插件 编译proto文件-->
<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.6.2</version>
    </extension>
  </extensions>
  <plugins>
    <plugin>
      <groupId>org.xolstice.maven.plugins</groupId>
      <artifactId>protobuf-maven-plugin</artifactId>
      <version>0.6.1</version>
      <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.17.3:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.42.0:exe:${os.detected.classifier}</pluginArtifact>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>compile-custom</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
</project>

2、导入Proto文件

这里的proto文件尽量和客户端的保持一致,完成和客户端步骤2同样的事儿。需要注意的是,在proto文件中,用package声明生成的Java类的包名,请与服务端实现类的包结构保持一致,这样才能正常地完成依赖导入和方法重写;

例如:

3、编写服务端实现类代码

  1. @GRpcService:用于标记这个类是一个gRPC服务端的实现类。它告诉Spring Boot框架将这个类注册为一个gRPC服务端,并自动处理gRPC请求。
  2. 继承自GreeterGrpc.GreeterImplBase类,表示它是rpc服务Greeter的实现类,在类中,我们可以重写rpc接口的实现方法,来处理接收到请求;
java 复制代码
/**
 * hello service impl
 *
 * @author yangyang
 * @date 2023/11/30
 */
@GRpcService
@Slf4j
public class HelloServiceImpl extends GreeterGrpc.GreeterImplBase {


    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
        // 获取客户端发送的请求消息
        String name = request.getName();
        // 构建响应消息
        HelloReply response = HelloReply.newBuilder()
        .setMessage("Hello, " + name + "!")
        .build();
        log.info("[grpc server]: response: {}", response);

        // 发送响应消息
        responseObserver.onNext(response);
        // 通知客户端响应已经完成
        responseObserver.onCompleted();
    }
}

4、配置端口号,启动服务

可通过此配置修改rpc的端口号(默认6565)

yaml 复制代码
grpc:
  # grpc server port
  port: 6565
server:
  port: 8081

服务启动后,可以在日志中看到端口信息

可以选择使用通过客户端发送请求来测试服务,或者使用postman等工具发送rpc接口。至此,一个简单且完整的SpringBoot gRPC客户端与服务端开发完成!

酸奶小肥阳原创,欢迎阅读点赞加收藏,关注我随时与我技术交流吧😄

相关推荐
llz_1123 小时前
web-第二次课后作业
前端·后端·web
红尘散仙8 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记10 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆10 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪10 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball61611 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_25183645711 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao11 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒12 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端
ayqy贾杰13 小时前
基层管理的三板斧,在AI时代行不通了
前端·后端·团队管理