当前位置: 首页 > news >正文

21-java-grpc-demo-1

java #grpc

Java gRPC 实战:从零构建高效的RPC服务

代码仓库

https://gitee.com/suveng/java_grpc_demo_1

引言:为什么选择gRPC?

在现代分布式系统中,服务间通信已成为架构设计的核心环节。传统的RESTful API虽然简单易用,但在高性能场景下往往显得力不从心。gRPC作为Google开源的高性能RPC框架,凭借其基于HTTP/2的传输协议、Protocol Buffers的序列化格式以及强大的代码生成能力,正在成为微服务架构中的首选通信方案。

本文将通过一个完整的Java gRPC示例项目,深入探讨如何从零开始构建一个高效的RPC服务。我们将从项目结构、关键代码实现到执行流程,全方位解析gRPC的工作原理和最佳实践,帮助读者快速掌握这一强大的技术栈。


项目概览与技术栈

我们的示例项目是一个简单的问候服务,包含服务器端和客户端实现。项目采用Maven构建,使用Java 21作为开发语言,集成了gRPC 1.58.0和Protocol Buffers 3.21.12。

项目结构


java-grpc-demo/├── pom.xml                              # Maven配置文件├── src/│   └── main/│       ├── java/com/example/grpc/│       │   ├── GreeterServer.java      # gRPC服务器实现│       │   ├── GreeterClient.java      # gRPC客户端实现│       │   └── DemoApp.java            # 演示应用程序│       └── proto/│           └── greeting.proto           # Protocol Buffers定义文件└── README.md                           # 项目说明文档

核心依赖配置

pom.xml中,我们配置了以下关键依赖:


<dependencies>    <!-- gRPC核心依赖 -->    <dependency>        <groupId>io.grpc</groupId>        <artifactId>grpc-netty-shaded</artifactId>        <version>${grpc.version}</version>    </dependency>    <dependency>        <groupId>io.grpc</groupId>        <artifactId>grpc-protobuf</artifactId>        <version>${grpc.version}</version>    </dependency>    <dependency>        <groupId>io.grpc</groupId>        <artifactId>grpc-stub</artifactId>        <version>${grpc.version}</version>    </dependency>    <!-- Protocol Buffers支持 -->    <dependency>        <groupId>com.google.protobuf</groupId>        <artifactId>protobuf-java</artifactId>        <version>${protobuf.version}</version>    </dependency></dependencies>

关键代码解析

1. Protocol Buffers服务定义

gRPC的核心是使用Protocol Buffers定义服务接口。在我们的greeting.proto文件中:


syntax = "proto3";package com.example.grpc;option java_package = "com.example.grpc";option java_multiple_files = true;// 定义问候服务service Greeter {  // 发送问候的RPC方法  rpc SayHello (HelloRequest) returns (HelloReply) {}  // 再次发送问候的RPC方法  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}}// 请求消息,包含用户名message HelloRequest {  string name = 1;}// 响应消息,包含问候语message HelloReply {  string message = 1;}

这个定义文件描述了:

  • 一个名为Greeter的服务,包含两个RPC方法

  • 请求消息HelloRequest,包含一个字符串字段name

  • 响应消息HelloReply,包含一个字符串字段message

2. 服务器端实现

GreeterServer.java中,我们实现了gRPC服务器:


public class GreeterServer {  private static final Logger logger = Logger.getLogger(GreeterServer.class.getName());  private Server server;  private void start() throws IOException {    // 服务器监听端口50051    int port = 50051;    server = ServerBuilder.forPort(port)        .addService(new GreeterImpl())  // 添加服务实现        .build()        .start();    logger.info("Server started, listening on " + port);    // 添加JVM关闭钩子,确保服务器优雅关闭    Runtime.getRuntime().addShutdownHook(new Thread() {      @Override      public void run() {        System.err.println("*** shutting down gRPC server since JVM is shutting down");        try {          GreeterServer.this.stop();        } catch (InterruptedException e) {          e.printStackTrace(System.err);        }        System.err.println("*** server shut down");      }    });  }  // 服务实现类,继承自动生成的基类  static class GreeterImpl extends GreeterGrpc.GreeterImplBase {    @Override    public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {      // 构建响应消息      HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();      // 发送响应      responseObserver.onNext(reply);      // 标记响应完成      responseObserver.onCompleted();    }    @Override    public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) {      HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();      responseObserver.onNext(reply);      responseObserver.onCompleted();    }  }}

服务器实现的关键点:

  • 使用ServerBuilder创建服务器,监听指定端口

  • 通过addService()方法注册服务实现

  • 实现服务接口时,需要处理StreamObserver来完成响应

  • 添加JVM关闭钩子确保服务器优雅关闭

3. 客户端实现

GreeterClient.java中,我们实现了gRPC客户端:


public class GreeterClient {  private final ManagedChannel channel;  private final GreeterGrpc.GreeterBlockingStub blockingStub;  // 构造客户端,连接到指定主机和端口  public GreeterClient(String host, int port) {    this(ManagedChannelBuilder.forAddress(host, port)        // 使用明文传输(生产环境应使用TLS)        .usePlaintext()        .build());  }  // 问候方法,调用服务器的两个RPC方法  public void greet(String name) {    logger.info("Will try to greet " + name + " ...");    HelloRequest request = HelloRequest.newBuilder().setName(name).build();    try {      // 调用SayHello方法      HelloReply response = blockingStub.sayHello(request);      logger.info("Greeting: " + response.getMessage());      // 调用SayHelloAgain方法      response = blockingStub.sayHelloAgain(request);      logger.info("Greeting again: " + response.getMessage());    } catch (StatusRuntimeException e) {      logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());    }  }}

客户端实现的关键点:

  • 使用ManagedChannelBuilder创建到服务器的连接

  • 通过GreeterGrpc.newBlockingStub()创建阻塞式存根

  • 构建请求消息并调用RPC方法

  • 处理可能的RPC异常

4. 演示应用程序

DemoApp.java是一个完整的演示应用程序,展示了如何同时运行服务器和客户端:


public class DemoApp {    public static void main(String[] args) {        System.out.println("=== Java gRPC Demo ===");        // 在单独线程中启动服务器        ExecutorService serverExecutor = Executors.newSingleThreadExecutor();        serverExecutor.submit(() -> {            try {                GreeterServer.main(new String[]{});            } catch (Exception e) {                System.err.println("Server error: " + e.getMessage());            }        });        // 给服务器启动时间        try {            Thread.sleep(2000);        } catch (InterruptedException e) {            Thread.currentThread().interrupt();        }        // 运行客户端测试        try {            GreeterClient client = new GreeterClient("localhost", 50051);            System.out.println("\n--- Testing with 'World' ---");            client.greet("World");            System.out.println("\n--- Testing with 'gRPC' ---");            client.greet("gRPC");            System.out.println("\n--- Testing with 'Java' ---");            client.greet("Java");            client.shutdown();        } catch (Exception e) {            System.err.println("Client error: " + e.getMessage());        }        // 关闭服务器        try {            System.out.println("\nShutting down server...");            serverExecutor.shutdownNow();            serverExecutor.awaitTermination(5, TimeUnit.SECONDS);            System.out.println("Demo completed successfully!");        } catch (InterruptedException e) {            Thread.currentThread().interrupt();            System.err.println("Shutdown interrupted");        }    }}

执行流程详解

1. 项目构建流程

gRPC项目的构建流程包含以下关键步骤:

  1. Protocol Buffers编译

- Maven的protobuf-maven-plugin插件会自动编译.proto文件

- 生成Java类和gRPC服务基类

- 生成的类位于target/generated-sources/protobuf目录

  1. Java代码编译

- 使用标准的Maven编译插件编译Java源代码

- 包含生成的Protocol Buffers代码

  1. 打包与运行

- 使用exec-maven-plugin插件运行演示应用程序

2. 运行时执行流程

当运行演示应用程序时,执行流程如下:

  1. 服务器启动

- 创建GreeterServer实例

- 绑定到端口50051

- 注册GreeterImpl服务实现

- 等待客户端连接

  1. 客户端连接

- 创建到服务器的ManagedChannel

- 创建GreeterBlockingStub

- 构建请求消息

  1. RPC调用

- 客户端调用sayHello()方法

- 服务器接收请求并处理

- 构建响应消息并返回

- 客户端接收响应

  1. 优雅关闭

- 客户端关闭通道

- 服务器关闭并释放资源

3. 数据流转过程

gRPC的数据流转过程体现了其高效性:

  1. 请求序列化

- 客户端将HelloRequest对象序列化为二进制格式

- 使用Protocol Buffers的高效序列化算法

  1. HTTP/2传输

- 序列化后的数据通过HTTP/2连接传输

- 利用HTTP/2的多路复用和头部压缩特性

  1. 服务端处理

- 服务器接收二进制数据并反序列化为HelloRequest对象

- 处理业务逻辑并构建HelloReply响应

  1. 响应返回

- 响应对象序列化为二进制格式

- 通过HTTP/2连接返回给客户端

- 客户端反序列化并处理响应


总结与展望

通过这个简单的Java gRPC示例项目,我们深入了解了gRPC的核心概念和实现细节。从Protocol Buffers的服务定义到服务器端和客户端的具体实现,再到完整的执行流程,我们看到了gRPC如何通过高效的二进制协议和代码生成能力,为分布式系统提供强大的通信支持。

gRPC的核心优势

  1. 高性能:基于HTTP/2和Protocol Buffers,提供比传统REST API更高的性能

  2. 强类型:通过代码生成确保接口契约的强类型检查

  3. 多语言支持:支持多种编程语言的互操作性

  4. 流式处理:支持客户端流、服务端流和双向流通信

  5. 易于集成:与现有系统和技术栈良好集成

实际应用场景

gRPC特别适用于以下场景:

  • 微服务架构中的内部服务通信

  • 高性能API服务

  • 实时通信系统

  • 移动应用后端服务

  • 大数据处理系统

进一步探索

对于想要深入学习gRPC的开发者,建议探索以下主题:

  • gRPC的四种服务类型:一元、客户端流、服务端流和双向流

  • gRPC的安全机制:TLS认证和令牌认证

  • gRPC的拦截器机制:用于日志记录、监控和认证

  • gRPC与Spring Boot等框架的集成

  • gRPC的服务发现和负载均衡

gRPC作为现代分布式系统的重要组件,正在改变我们构建服务间通信的方式。通过掌握这一技术,开发者能够构建更加高效、可靠和可扩展的分布式应用。希望本文能够为您的gRPC学习之旅提供有价值的参考和指导。

http://www.hskmm.com/?act=detail&tid=33653

相关文章:

  • AI元人文:价值舞台
  • 2025年10月AI搜索优化推荐榜单:基于全平台实测数据的中立对比与决策指南
  • 【AI绘画】你有多久没有打开SD了?
  • 2025年10月豆包关键词排名优化推荐对比榜:企业选购的客观决策参考
  • 2025年10月豆包关键词排名优化推荐榜单:从核心技术到服务流程的系统化评价
  • php数据验证 + 过滤 + 参数绑定
  • Microsoft AI Genius | 用 MCP 解锁实时数据,重新定义交互边界
  • 2025年10月北京geo优化公司推荐榜:基于全平台实测数据的中立对比与选购指南
  • 2025年10月geo优化供应商推荐榜:十强对比评测与中立选购指南
  • 2025年拉链厂家推荐排行榜,TAB拉链,大棕拉链,金属拉链,树脂拉链,服装拉链,尼龙拉链,防水拉链,隐形拉链,男装拉链,女装拉链公司推荐榜!
  • 2025年10月geo优化服务商推荐榜单:基于全平台实测数据的中立对比与避坑指南
  • 前沿技术研究研讨会聚焦AI与机器人创新
  • 2025年10月geo优化推荐榜单:十强服务商对比评测与避坑指南
  • 2025年10月geo公司推荐对比评测:聚焦技术参数与服务透明度的实用攻略
  • 2025年10月geo公司推荐榜:基于全平台同步优化能力的中立对比与选购指南
  • 2025年10月geo服务商推荐榜:十强对比与中立评测助您精准选型
  • 2025年10月geo服务商推荐榜全解析:以跨平台同步率为核心指标的决策指南
  • [动态规划]CF1271D Portals
  • 常见数据结构长度的获取
  • 2025年10月GEO推荐榜单:十家技术服务商深度对比与中立评测
  • 2025年10月GEO推荐榜:十强服务商全维度对比与中立选购指南
  • 2025年10月geo推荐对比:十强服务商资质、成效、售后全梳理
  • 2025年10月办公家具公司推荐榜单:基于真实案例的采购决策参考
  • 逆向 | 对python函数进行hook的最简单方式
  • 2025年10月deepseek排名优化推荐榜:十强服务商全维度对比与中立评测
  • 2025年10月deepseek排名优化推荐榜:十强服务商多维对比与中立选购指南
  • 【】
  • 2025年10月洗碗机品牌推荐榜:以市占率增幅与专利表现为核心的系统评估
  • 2025年10月deepseek关键词排名优化推荐榜单:基于多维度实测与公开数据的对比分析
  • 2025年10月AI搜索营销推荐对比榜:基于算法适配与行业落地的深度观察