百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

gRPC Java 的开发StepByStep(javarpc原理)

ccwgpt 2025-06-03 20:51 11 浏览 0 评论


一、环境准备

1. 安装依赖

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

2. 添加 Maven 依赖

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

<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 的结合,可以高效地构建跨语言、高性能的分布式系统。

相关推荐

Java开发中的区块链技术应用:让代码更“链”接未来

Java开发中的区块链技术应用:让代码更“链”接未来嘿,各位Java开发者们!今天咱们就来聊聊一个超级热门的话题——区块链技术在Java开发中的应用。可能有些人听到区块链就想到比特币,但其实区块链的应...

gRPC Java 的开发StepByStep(javarpc原理)

一、环境准备1.安装依赖JDK:确保安装Java8或更高版本(推荐Java11+)。构建工具:选择Maven或Gradle(以下示例以Maven为主)。Protobuf编译器:...

谷歌发布开源LMEval框架:打破AI模型比较壁垒

IT之家5月27日消息,科技媒体TheDecoder昨日(5月26日)发布博文,报道称谷歌推出开源框架LMEval,为大语言模型和多模态模型提供标准化的评测工具。评测新型AI...

简约轻量的 VPN 客户端:LightVPN

Android自带的VPN需要设定锁屏密码才能启用,显然对于使用滑动或图案解锁的VPN用户来说,这是极为不友好的。为了改善这个情况,@喝雪碧的虾PeterCxy开发出了LightVPN这...

如何有效的去除安卓手机软件中的广告

【搞科技教程】安卓软件多同时广告也多,时不时的弹出来还一条条的切换,费流量的同时一不小心点到了还跳转了页面,这在玩游戏看视频的时候尤其令人烦躁。小安推荐大家一个轻量,高效的去除广告工具MinMinGu...

四款精品安卓软件推荐:让你的手机流畅的不像安卓机

目前国产软件的乱象,大部分软件不断后台自启,相互唤醒,这也是为什么安卓手机使用一段时间后就变卡的原因,今天小编为大家带来四款软件,能让你的手机流畅的像刚买时一样。绿色守护休眠进程和省电必备神器,最佳控...

生命不息,折腾不止:在 Android 上自制单手模式

手机屏幕做大,在视觉体验上带来的提升是非常明显的,但也因为屏幕变大,单手操作已不再那么现实。针对这种情况,各大厂商都相继推出了相应的解决方案,Android阵营比较有代表性的有魅族、锤子的下拉悬停和...

Windows11安卓增强指南(win11 安卓 效率)

在Win11上,让人感受最深的莫过于可以运行安卓格式的APK软件,但是对于更加发烧的玩家来说,安卓系统没有ROOT,就无法实现一些骚操作,那么今天就来看看怎么给Win11的WSA加上ROOT吧。注意:...

2025年安卓虚拟机APP推荐TOP5(附下载教程)

身为25岁非二元性别的自媒体人,我视频剪辑、内容创作样样精通。多平台运营离不开安卓虚拟机APP。今天,就来聊聊2025年我最爱的5款虚拟机APP,附上教程,助你创作更高效!一、安卓虚拟机APP有什么用...

全民风险管理理论之COSO-ERM(全面风险管理的参与者)

萨班斯-奥克斯利法案内控体系COSO-ERM,2004八个要素COSO——ERM(2017版)框架五要素20个原则企业的经营目标不是价值最大化风险管理各要素间的关系各级关系全面风险管理与内...

透过照片学习摆姿技巧 你能拍出妹子的曲线么?

大多数人认为拍妹子都一个套路,但随着社会的发展,人们受到外来文化的影响越来越多,个性的照片也越来越被大家所接受。到底怎样的一幅人像照才是好照片,今天我们就从模特摆姿的方面来谈一谈人像照片中怎样能够完美...

手把手教你拍好局部风光!(如何拍好风光片)

外出旅行,游历名山大川、江河湖海,日升日落……总能看到绝佳的风景,有时置身于无与伦比的风景中反而容易眼花缭乱、迷失自己。我们不仅要欣赏远处雄浑壮阔的雪山,但是也不要忽略脚下和身边的局部优美风光。下面就...

C# 从代码入门 Mysql 数据库事务(c#数据库操作实例)

目录生成数据库数据Mysql数据库事务基础数据库的并发一致性问题数据库事务的隔离级别BeginTransaction()和TransactionScope的区别BeginTransaction...

真香预警!尼康大炮500mm F4 FL E试用心得

NicolasStettler是一位来自瑞士的17岁野生动物摄影师,他最近购买了尼康最新一代长焦镜头AF-S尼克尔500mmf/4EFLEDVR,并将其与他的旧镜头进行了比较,以下是他的详细...

佳能RF 50mm f1.2L USM 被吹捧还是凭实力?新老对比能否一战?

镜头的定位佳能RF50mmf1.2LUSM是佳能EOSR全画幅无反光镜系统的标准定焦镜头RF50mmf1.2LUSM可以看作是之前12年推出的EF50mmf1.2LUSM的继承者。...

取消回复欢迎 发表评论: