没腿的鸟 发表于 2024-11-22 13:56:30

零底子入门gRPC:从 0 实现一个Hello World

在之前解说 Nacos 注册中央的过程中,我曾简要提到过 gRPC,主要是由于 Nacos 的最新版已经采用了 gRPC 作为其核心通信协议。这一变化带来了显著的性能优化,尤其在心跳检测、健康检查等接口的消息传输上,gRPC 可以有用减少网络负担和延迟,从而提高系统的整体效率。
所以,今天我们将简要了解一下 gRPC 这种通信协议是如何运作的,并通过一个简单的 HelloWorld 示例来展示它的基本利用方式。
gRPC

gRPC(全称:gRPC Remote Procedure Call)是一个由 Google 开发的高性能、开源的远程过程调用(RPC)框架,它基于 HTTP/2 协议,并且采用了 Protocol Buffers(Protobuf)作为接口界说语言。gRPC 旨在简化和优化微服务架构中的服务间通信,提供高效、可靠的通信机制,适用于大规模分布式系统。
gRPC 的通信流程大致如下:

[*]接口界说:开发者利用 Protobuf 界说服务接口(.proto 文件)。该文件形貌了服务的 RPC 方法、哀求和相应消息类型。
[*]代码生成:利用 Protobuf 编译器(protoc)根据 .proto 文件生成对应语言的客户端和服务器代码。
[*]客户端调用:客户端通过 gRPC 客户端 API 调用远程方法,发送哀求并接收相应。gRPC 客户端和服务器之间的通信是透明的,客户端只必要像调用本地方法一样调用远程方法。
[*]服务器实现:服务器端实现 .proto 文件中界说的 RPC 方法,并通过 gRPC 框架处置惩罚客户端的哀求。
[*]通信协议:gRPC 利用 HTTP/2 协议举行高效的通信,基于 Protobuf 编码和解码哀求和相应数据。
快速入门

新建项目

按照我们刚才讨论的通信流程,接下来我们将通过一个简单的示例来实现这一过程。首先,我们必要创建一个新的项目,项目的名称可以根据个人喜欢举行定名。如图所示:
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161016391-1907631678.png
项目结构

接下来,我们将在刚才创建的项目中进一步细化结构,我们整体的项目结构如下:
│pom.xml

├─grpc-api
││.gitignore
││pom.xml
││
│├─src
││├─main
│││├─java
││││└─org
││││      └─xiaoyu
││││          │Main.java
││││          └─test
│││└─proto
│││          hello.proto
├─grpc-client
││pom.xml
│├─src
││├─main
│││├─java
││││└─org
││││      └─xiaoyu
││││          │Main.java
│││└─resources
│││          application.yml
└─grpc-server
│pom.xml
├─src
│├─main
││├─java
│││└─org
│││      └─xiaoyu
│││          │Main.java
│││          └─service
│││                  HelloWorldController.java
││└─resources
││          application.yaml
跟着上面的目次结构,我们必要创建子项目,如图所示:
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161025146-1913332693.png
接下来,我们将设置父项目与各子项目之间的依赖关系,以确保它们可以或许精确地协同工作。
项目依赖

父项目依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.6.7</version>
      <relativePath />
    </parent>
    <groupId>org.xiaoyu</groupId>
    <artifactId>grpc-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
      <module>grpc-client</module>
      <module>grpc-server</module>
      <module>grpc-api</module>
    </modules>

    <properties>
      <maven.compiler.source>8</maven.compiler.source>
      <maven.compiler.target>8</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
      <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.51.0</version>
      </dependency>

      <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.51.0</version>
      </dependency>

      <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.51.0</version>
      </dependency>

      <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java-util</artifactId>
            <version>3.7.1</version>
      </dependency>

      <dependency>
            <groupId>com.googlecode.protobuf-java-format</groupId>
            <artifactId>protobuf-java-format</artifactId>
            <version>1.4</version>
      </dependency>

    </dependencies>

    <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.12.0:exe:${os.detected.classifier}</protocArtifact>
                  <pluginId>grpc-java</pluginId>
                  <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.34.1:exe:${os.detected.classifier}</pluginArtifact>
                  
                  <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>

            
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                  
                  <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                              <source>${project.basedir}/src/main/gen</source>
                              <source>${project.basedir}/src/main/java</source>
                            </sources>
                        </configuration>
                  </execution>
                </executions>
            </plugin>

      </plugins>
    </build>
</project>client项目依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
      <groupId>org.xiaoyu</groupId>
      <artifactId>grpc-demo</artifactId>
      <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>grpc-client</artifactId>

    <properties>
      <maven.compiler.source>8</maven.compiler.source>
      <maven.compiler.target>8</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-client-spring-boot-starter</artifactId>
            <version>2.14.0.RELEASE</version>
      </dependency>
      <dependency>
            <groupId>org.xiaoyu</groupId>
            <artifactId>grpc-api</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
      </dependency>
    </dependencies>
</project>server的项目依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
      <groupId>org.xiaoyu</groupId>
      <artifactId>grpc-demo</artifactId>
      <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>grpc-server</artifactId>

    <properties>
      <maven.compiler.source>8</maven.compiler.source>
      <maven.compiler.target>8</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
      <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>2.14.0.RELEASE</version>
      </dependency>
      <dependency>
            <groupId>org.xiaoyu</groupId>
            <artifactId>grpc-api</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
      </dependency>
    </dependencies>

</project>proto接口界说

接下来,我们必要生成客户端和服务端的接口界说,并基于这些接口界说主动生成相关的代码。接口界说是整个 gRPC 通信的核心,它将明白服务端提供的 API 接口及其对应的消息格式,这为客户端和服务端之间的通信提供了底子。
为了高效地生成这些接口代码,我们可以借助一些主动化工具和 AI 助手来加速这一过程,简单问下即可。如图所示:
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161039820-172982213.png
然后复制过来简单改一下,代码如下:
syntax = "proto3";
import "google/protobuf/any.proto";

package org.xiaoyu.test;

option java_multiple_files = true;
option java_package = "org.xiaoyu.test";
option objc_class_prefix = "HelloWorld";

// 定义服务
service Greeter {
    // 定义一个 SayHello 方法,接收一个 HelloRequest 类型的请求,并返回一个 HelloReply 类型的响应
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 定义请求消息类型
message HelloRequest {
    string name = 1;
}

// 定义响应消息类型
message HelloReply {
    string message = 1;
}完成接口界说后,我们只需通过执行 mvn compile 命令,直接对 API 项目举行编译,即可主动生成与接口界说相关的全部代码类。这个过程将会根据我们在 .proto 文件中界说的 gRPC 服务和消息结构,主动生成相应的客户端和服务端代码,包括 Java 类、存根(stub)、消息类等。
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161046997-289114413.png
服务端

接下来,如果在编译或生成代码的过程中仍然遇到标题,大概对某些步调存在疑问,完全可以继承向 AI 助手寻求资助。AI 助手可以为我们提供针对性的标题解决方案和调试建议,无论是编译错误、依赖标题,还是代码生成后的一些设置标题,都能快速给出指导。如图所示:
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161053953-770741252.png
在生成了相关代码后,我们可以直接将这些代码复制到 server 项目中,方便我们举行服务端的开发和集成。同样地,当我们开始举行具体业务逻辑的实现时,AI 助手也能发挥重要作用。在实现服务端逻辑时,AI 助手不仅能主动补全代码,还可以基于项目的上下文和需求,智能推荐最佳的实现方式。
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161102124-1896685056.png
最终代码如下,很简单:
@GrpcService
public class HelloWorldController extends GreeterGrpc.GreeterImplBase {

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {

      responseObserver.onNext(HelloReply.newBuilder().setMessage("xiaoyu: Hello " + request.getName()).build());
      responseObserver.onCompleted();
    }
}服务端设置

我们必要简单设置一下服务端的监听接口,如下:
grpc:
server:
    port: 9090剩下的步调就是启动我们已经集成了 gRPC 服务的 Spring 项目。当我们运行项目时,Spring Boot 应用会主动加载并初始化相关的 gRPC 服务设置,并开始监听指定的端口。
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161108822-839646631.png
客户端

在客户端部门,我们必要举行一些手动设置,虽然目前尚未找到可以或许直接启动并主动设置的注解或工具。在这个阶段,客户端代码的编写相对简单,主要是利用从 API 项目生成的客户端代码来完成对服务端的哀求调用。尽管这部门无法完全主动化,我们可以通过直接利用生成的客户端代码来手动构建哀求对象,并发起 gRPC 调用,从而实现与服务端的通信。如下:
public class Main {
    public static void main(String[] args) {
      ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090)
                .usePlaintext()
                .build();

      // 创建一元式阻塞式存根
      GreeterGrpc.GreeterBlockingStub blockingStub = GreeterGrpc.newBlockingStub(channel);

      // 创建请求对象
      HelloRequest request = HelloRequest.newBuilder()
                .setName("World")
                .build();

      // 发送请求信息并接收响应
      HelloReply response = blockingStub.sayHello(request);

      // 处理信息响应
      System.out.println("Receivedresponse: " + response);

    }
}只需直接运行项目,即可成功启动并完成服务的全部设置。与其他服务接口的调用方式类似,我们在这里无需编写任何额外的接口调用代码,看下运行结果,如图所示:
https://img2024.cnblogs.com/blog/1423484/202411/1423484-20241119161114418-1479676816.png
总结

通过本文的解说,我们了解了 gRPC 作为一种高效的通信协议在微服务架构中的应用,特别是在与 Nacos 集成时带来的性能优化。gRPC 的高效性,得益于其基于 HTTP/2 协议和 Protobuf 的数据传输方式,使得跨服务通信更加迅速且可靠。本文通过 HelloWorld 示例演示了从接口界说到服务端和客户端的实现流程,充分展示了 gRPC 的强盛功能和易用性。
把握这一协议,不仅可以或许提拔服务间的通信效率,也为开发更具扩展性的分布式系统奠定了底子。最终,gRPC 作为微服务架构中的关键组件,其提供的性能优化和便捷性,必将在未来的项目中发挥重要作用。
我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位腾讯云创作之星、阿里云专家博主、华为云云享专家、掘金优秀作者。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 零底子入门gRPC:从 0 实现一个Hello World