专业的JAVA编程教程与资源

网站首页 > java教程 正文

gRPC Java 的开发StepByStep(javarpc原理)

temp10 2025-07-03 00:20:42 java教程 1 ℃ 0 评论


一、环境准备

1. 安装依赖

  • JDK:确保安装 Java 8 或更高版本(推荐 Java 11+)。
  • 构建工具:选择 Maven 或 Gradle(以下示例以 Maven 为主)。
  • Protobuf 编译器:用于编译 .proto 文件生成代码。
    • 下载地址:Protocol Buffers 下载。
    • 配置环境变量,确保 protoc 命令可在终端调用。

2. 添加 Maven 依赖

在 pom.xml 中引入 gRPC 和 Protobuf 相关库:

gRPC Java 的开发StepByStep(javarpc原理)

<dependencies>
    <!-- gRPC 核心库 -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty-shaded</artifactId>
        <version>1.61.0</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>1.61.0</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>1.61.0</version>
    </dependency>
    <!-- Protobuf 库 -->
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.25.1</version>
    </dependency>
</dependencies>

二、定义服务(.proto 文件)

在 src/main/proto 目录下创建 .proto 文件(如 helloworld.proto),定义 RPC 服务和消息类型:

syntax = "proto3";

// 包名(建议使用反向域名,如 com.example.grpc)
package helloworld;

// 指定生成的 Java 包名
option java_package = "com.example.grpc.helloworld";
option java_multiple_files = true; // 生成多个 Java 类

// 定义请求消息
message HelloRequest {
    string name = 1; // 字段编号 1
}

// 定义响应消息
message HelloResponse {
    string reply = 1; // 字段编号 1
}

// 定义服务接口
service Greeter {
    // 一元 RPC:客户端发送单个请求,服务端返回单个响应
    rpc SayHello (HelloRequest) returns (HelloResponse) {}
    
    // 服务器流 RPC:客户端发送单个请求,服务端返回多个响应
    rpc SayHelloStream (HelloRequest) returns (stream HelloResponse) {}
}

三、生成代码

通过 Protobuf 插件自动生成 gRPC 服务端和客户端代码。

1. Maven 配置(推荐)

在 pom.xml 中添加 protobuf-maven-plugin 插件,自动编译 .proto 文件并生成 Java 代码:

<build>
    <extensions>
        <!-- 用于检测操作系统,适配不同平台的 Protobuf 编译器 -->
        <extension>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>1.7.0</version>
        </extension>
    </extensions>
    <plugins>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.6.1</version>
            <configuration>
                <!-- Protobuf 编译器版本 -->
                <protocArtifact>com.google.protobuf:protoc:3.25.1:exe:${os.detected.classifier}</protocArtifact>
                <!-- gRPC Java 插件 -->
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.61.0:exe:${os.detected.classifier}</pluginArtifact>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal> <!-- 生成 Protobuf 代码 -->
                        <goal>compile-custom</goal> <!-- 生成 gRPC 代码 -->
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

2. 执行代码生成

运行以下命令生成代码:

mvn clean install

生成的代码位于
target/generated-sources/protobuf 目录,包含:

  • 消息类(如 HelloRequest.java、HelloResponse.java)。
  • 服务存根类(如 GreeterGrpc.java,包含服务端和客户端存根)。

四、实现服务端

1. 继承服务存根类

创建服务端实现类,继承 .proto 生成的 ImplBase 类(如 GreeterImplBase),并实现 RPC 方法:

package com.example.grpc.helloworld;

import io.grpc.stub.StreamObserver;

public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase {
    // 实现一元 RPC
    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
        String name = request.getName();
        String reply = "Hello, " + name + "!";
        // 构建响应
        HelloResponse response = HelloResponse.newBuilder().setReply(reply).build();
        // 发送响应并结束流
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }

    // 实现服务器流 RPC(返回多个响应)
    @Override
    public void sayHelloStream(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
        String name = request.getName();
        // 分三次发送响应
        responseObserver.onNext(HelloResponse.newBuilder().setReply("Hello 1, " + name).build());
        responseObserver.onNext(HelloResponse.newBuilder().setReply("Hello 2, " + name).build());
        responseObserver.onNext(HelloResponse.newBuilder().setReply("Hello 3, " + name).build());
        responseObserver.onCompleted(); // 必须调用以结束流
    }
}

2. 启动服务端

创建主类,绑定端口并启动 gRPC 服务:

package com.example.grpc.server;

import com.example.grpc.helloworld.GreeterGrpc;
import com.example.grpc.helloworld.GreeterServiceImpl;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;

public class GrpcServer {
    private static final int PORT = 50051;

    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建服务端构建器
        Server server = ServerBuilder.forPort(PORT)
            .addService(new GreeterServiceImpl()) // 注册服务实现
            .build();

        // 启动服务
        server.start();
        System.out.println("Server started on port " + PORT);

        // 阻塞线程,防止服务退出
        server.awaitTermination();
    }
}

五、实现客户端

1. 使用存根调用 RPC

创建客户端类,通过生成的存根(如 GreeterStub)调用服务端方法:

package com.example.grpc.client;

import com.example.grpc.helloworld.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

public class GrpcClient {
    public static void main(String[] args) {
        // 创建连接到服务端的通道(建议使用 SSL 加密,此处为明文示例)
        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
            .usePlaintext() // 禁用 SSL(生产环境需启用)
            .build();

        // 创建异步存根(默认)
        GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

        // 调用一元 RPC
        HelloRequest request = HelloRequest.newBuilder().setName("World").build();
        stub.sayHello(request, new StreamObserver<HelloResponse>() {
            @Override
            public void onNext(HelloResponse response) {
                System.out.println("Unary response: " + response.getReply());
            }

            @Override
            public void onError(Throwable t) {
                System.err.println("RPC error: " + t.getMessage());
            }

            @Override
            public void onCompleted() {
                System.out.println("Unary call completed.");
            }
        });

        // 调用服务器流 RPC
        stub.sayHelloStream(request, new StreamObserver<HelloResponse>() {
            @Override
            public void onNext(HelloResponse response) {
                System.out.println("Stream response: " + response.getReply());
            }

            @Override
            public void onError(Throwable t) {
                System.err.println("Stream error: " + t.getMessage());
            }

            @Override
            public void onCompleted() {
                System.out.println("Stream call completed.");
            }
        });

        // 关闭通道(建议使用 try-with-resources)
        channel.shutdown();
    }
}

六、运行与测试

  1. 启动服务端:运行 GrpcServer 主类,服务监听在 50051 端口。
  2. 运行客户端:运行 GrpcClient 主类,观察控制台输出是否收到服务端响应。
  3. 测试工具
    • 使用 grpcurl 命令行工具验证(需安装):
grpcurl -plaintext localhost:50051 helloworld.Greeter/SayHello -d '{"name":"Test"}'
    • 使用 Postman(需安装 gRPC 插件)或 IDE 内置工具调试。

七、高级特性(可选)

  1. 认证与加密
    • 使用 SSL/TLS 实现安全连接(参考 gRPC Java 安全指南)。
    • 添加令牌认证(如 JWT)。
  1. 拦截器(Interceptor)
    • 全局拦截器用于日志记录、限流、权限校验等:
// 服务端添加拦截器
Server server = ServerBuilder.forPort(PORT)
    .intercept(new ServerInterceptor() { /* 实现拦截逻辑 */ })
    .build();
  1. 负载均衡
    • 使用 gRPC 内置负载均衡策略(如 round-robin)或第三方组件(如 Consul)。
  1. 异步与非阻塞编程
    • 使用 ListenableFuture 或响应式编程库(如 RxJava)处理异步操作。

注意事项

  • 版本兼容性:确保 gRPC、Protobuf 插件和依赖库版本一致,避免兼容性问题。
  • 流式 RPC
    • 客户端流和双向流需通过 StreamObserver 逐消息处理。
    • 务必调用 onCompleted() 结束流,否则可能导致内存泄漏或阻塞。
  • 生产环境
    • 启用 SSL 加密(useTransportSecurity())。
    • 配置连接池和重试机制(通过 ManagedChannelBuilder 参数)。

通过以上步骤,可快速搭建基于 gRPC Java 的微服务架构,实现高效的远程过程调用。### gRPC Java 开发步骤指南

gRPC 是一个高性能、开源的远程过程调用 (RPC) 框架,可以在任何环境中运行。以下是使用 Java 进行 gRPC 开发的基本步骤:

1. 定义服务接口 (.proto 文件)

首先需要使用 Protocol Buffers 定义服务接口和消息类型。创建一个 .proto 文件(例如 hello.proto):

syntax = "proto3";

package helloworld;  // 定义包名

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

message HelloResponse {
  string message = 1;
}

// 定义服务接口
service Greeter {
  // 一元 RPC 方法
  rpc SayHello (HelloRequest) returns (HelloResponse);
  
  // 服务器流 RPC 方法
  rpc SayHelloStream (HelloRequest) returns (stream HelloResponse);
}

2. 添加依赖

在 pom.xml (Maven) 或 build.gradle (Gradle) 中添加 gRPC 依赖:

Maven 配置:

<dependencies>
  <!-- gRPC 核心库 -->
  <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>
</dependencies>
<!-- 用于生成 gRPC 代码的插件 -->
<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.7.0</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.3:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.58.0:exe:${os.detected.classifier}</pluginArtifact>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>compile-custom</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Gradle 配置:

plugins {
  id 'com.google.protobuf' version '0.9.4'
}

dependencies {
  implementation 'io.grpc:grpc-netty-shaded:1.58.0'
  implementation 'io.grpc:grpc-protobuf:1.58.0'
  implementation 'io.grpc:grpc-stub:1.58.0'
}

protobuf {
  protoc {
    artifact = 'com.google.protobuf:protoc:3.24.3'
  }
  plugins {
    grpc {
      artifact = 'io.grpc:protoc-gen-grpc-java:1.58.0'
    }
  }
  generateProtoTasks {
    all()*.plugins {
      grpc {}
    }
  }
}

3. 生成 gRPC 代码

使用 Maven 或 Gradle 插件生成 Java 代码:

# Maven
mvn clean compile

# Gradle
gradle clean build

生成的代码会放在
target/generated-sources/protobuf (Maven) 或
build/generated/source/proto (Gradle) 目录下。

4. 实现服务端

创建一个类继承自
GreeterGrpc.GreeterImplBase 并实现服务方法:

import io.grpc.stub.StreamObserver;

public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase {

  // 实现一元 RPC 方法
  @Override
  public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
    HelloResponse response = HelloResponse.newBuilder()
        .setMessage("Hello, " + request.getName())
        .build();
    responseObserver.onNext(response);
    responseObserver.onCompleted();
  }

  // 实现服务器流 RPC 方法
  @Override
  public void sayHelloStream(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
    for (int i = 0; i < 3; i++) {
      HelloResponse response = HelloResponse.newBuilder()
          .setMessage("Hello, " + request.getName() + " (" + i + ")")
          .build();
      responseObserver.onNext(response);
      
      // 模拟延迟
      try { Thread.sleep(1000); } catch (InterruptedException e) {}
    }
    responseObserver.onCompleted();
  }
}

创建服务器启动类:

import io.grpc.Server;
import io.grpc.ServerBuilder;

public class GreeterServer {
  private final int port;
  private final Server server;

  public GreeterServer(int port) {
    this.port = port;
    this.server = ServerBuilder.forPort(port)
        .addService(new GreeterServiceImpl())
        .build();
  }

  public void start() throws Exception {
    server.start();
    System.out.println("Server started, listening on " + port);
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      System.err.println("*** shutting down gRPC server since JVM is shutting down");
      GreeterServer.this.stop();
      System.err.println("*** server shut down");
    }));
  }

  public void stop() {
    if (server != null) {
      server.shutdown();
    }
  }

  public void blockUntilShutdown() throws InterruptedException {
    if (server != null) {
      server.awaitTermination();
    }
  }

  public static void main(String[] args) throws Exception {
    GreeterServer server = new GreeterServer(50051);
    server.start();
    server.blockUntilShutdown();
  }
}

5. 实现客户端

创建客户端类调用服务:

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

public class GreeterClient {
  private final ManagedChannel channel;
  private final GreeterGrpc.GreeterBlockingStub blockingStub;
  private final GreeterGrpc.GreeterStub asyncStub;

  public GreeterClient(String host, int port) {
    this.channel = ManagedChannelBuilder.forAddress(host, port)
        .usePlaintext()  // 非 SSL/TLS 连接,仅用于开发环境
        .build();
    this.blockingStub = GreeterGrpc.newBlockingStub(channel);
    this.asyncStub = GreeterGrpc.newStub(channel);
  }

  public void shutdown() throws InterruptedException {
    channel.shutdown().awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS);
  }

  // 调用一元 RPC
  public void greet(String name) {
    HelloRequest request = HelloRequest.newBuilder().setName(name).build();
    HelloResponse response;
    
    try {
      response = blockingStub.sayHello(request);
      System.out.println("Greeting: " + response.getMessage());
    } catch (Exception e) {
      System.err.println("RPC failed: " + e.getMessage());
    }
  }

  // 调用服务器流 RPC
  public void greetStream(String name) {
    HelloRequest request = HelloRequest.newBuilder().setName(name).build();
    
    asyncStub.sayHelloStream(request, new StreamObserver<HelloResponse>() {
      @Override
      public void onNext(HelloResponse response) {
        System.out.println("Stream response: " + response.getMessage());
      }

      @Override
      public void onError(Throwable t) {
        System.err.println("Stream error: " + t.getMessage());
      }

      @Override
      public void onCompleted() {
        System.out.println("Stream completed");
      }
    });
  }

  public static void main(String[] args) throws Exception {
    GreeterClient client = new GreeterClient("localhost", 50051);
    try {
      // 调用一元 RPC
      client.greet("World");
      
      // 调用服务器流 RPC
      client.greetStream("Streaming World");
      
      // 等待流响应完成
      Thread.sleep(5000);
    } finally {
      client.shutdown();
    }
  }
}

6. 运行应用程序

  1. 启动服务器:
java GreeterServer
  1. 启动客户端:
java GreeterClient

7. 高级特性(可选)

  • 认证与安全:配置 TLS/SSL 加密连接。
  • 拦截器:添加日志、权限验证等功能。
  • 负载均衡:实现客户端负载均衡策略。
  • 错误处理:统一处理 RPC 异常。

总结

gRPC Java 开发的核心步骤:

  1. 定义 .proto 文件
  2. 添加依赖并生成代码
  3. 实现服务端逻辑
  4. 编写客户端调用代码
  5. 测试和部署

通过 Protocol Buffers 和 gRPC 的结合,可以高效地构建跨语言、高性能的分布式系统。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表