【橘子分布式】gRPC(编程篇-上)

一、简介

我们之前学习了grpc的一些理论知识,现在我们开始正式进入编程环节。
我们的项目结构和之前的thrift结构还是一样的,一个common,一个client,一个server。只不过在grpc这里common它一般叫做api模块。还是放置一些公共的实体类,业务service类之类的。

二、项目结构

1. xxxx-api 模块 定义 protobuf的idl语言 并且通过命令创建对应的通用代码,包括实体类和service,其他模块统一引入即可。
2. xxxx-server模块1. 实现api模块中定义的服务接口2. 发布gRPC服务 (创建服务端程序,提供对外服务)
3. xxxx-clien模块1. 创建服务端stub(代理)2. 基于代理(stub) RPC调用。

1、代码编写

先创建一个rpc-grpc-api模块。

1.1、创建proto文件

我们在模块目录下创建一个proto目录来管理我们的.proto文件。
然后在该目录下创建一个hello.proto文件用来编写idl语言。

// 定义proto文件版本号
syntax = "proto3";// 生成一个java类即可
option java_multiple_files = false;
// 生成的java类的包名
option java_package = "com.levi";
// 外部类,这里就是HelloProto,实际开发你可以有多个proto管理不同业务类,然后各自的外部类都可以。比如OrderService就是Order.proto 外部类就是OrderProto
option java_outer_classname = "HelloProto";// 定义请求接口参数
message HelloRequest{string name = 1;
}// 定义接口响应参数
message HelloResponse{string result = 1;
}// 定义服务
service HelloService{/* 简单rpc,参数为HelloRequest类型,返回类型为HelloResponse */rpc hello(HelloRequest) returns (HelloResponse){}
}

然后我们就用protoc命令来翻译这个idl。

1.1、命令行生成IDL

如同之前thrift一样,我们在这里也是要先编写idl的部分。我们需要首先在.proto后缀的文件中编写protobuf的IDL。
然后使用protoc命令把proto文件中的IDL 转换成编程语言 ,我们之前已经安装过protobuf环境了,所以可以直接使用。
具体命令格式为

protoc  --java_out=生成的java代码路径   依赖的.proto文件
如果你要翻译为go语言,那就是protoc -go_out ......

举个例子就是:

protoc --java_out=/src/java  /src/proto/hello.proto

但是这种我们需要在终端操作,不太方便。还好idea的maven插件支持了这个能力。

1.2、maven插件支持

maven插件 进行protobuf IDL文件的编译,并把他放置IDEA具体位置。这个能力的支持来自于一个grpc-java开源项目,我们看到它对于maven很方便的支持了能力,我们先创建一个模块来引入这个maven配置。

<?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>com.levi</groupId><artifactId>rpc</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>rpc-grpc-api</artifactId><properties><java.version>11</java.version><grpc-netty-shaded.version>1.73.0</grpc-netty-shaded.version><grpc-protobuf.version>1.73.0</grpc-protobuf.version><grpc-stub.version>1.73.0</grpc-stub.version><annotations-api.version>6.0.53</annotations-api.version><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--grpc的http2就是通过netty实现的--><dependency><groupId>io.grpc</groupId><artifactId>grpc-netty-shaded</artifactId><version>${grpc-netty-shaded.version}</version><scope>runtime</scope></dependency><!--支持protobuf的序列化--><dependency><groupId>io.grpc</groupId><artifactId>grpc-protobuf</artifactId><version>${grpc-protobuf.version}</version></dependency><!--支持grpc代理--><dependency><groupId>io.grpc</groupId><artifactId>grpc-stub</artifactId><version>${grpc-stub.version}</version></dependency><dependency> <!-- necessary for Java 9+ --><groupId>org.apache.tomcat</groupId><artifactId>annotations-api</artifactId><version>${annotations-api.version}</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><!--com.google.protobuf:protoc这个命令是生成grpc的实体message的,os.detected.classifier是maven的一个内置系统参数,用来获取本机操作系统类型,这里是获取本机的操作系统类型,然后根据操作系统类型来获取protoc的命令,无需你自己写死,这里maven会自己获取--><protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact><!--grpc-java--><pluginId>grpc-java</pluginId><!--io.grpc:protoc-gen-grpc-java这个命令是支持grpc的service服务的--><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.73.0:exe:${os.detected.classifier}</pluginArtifact></configuration><executions><execution><goals><!--goals是maven执行的命令,类似于clean或者install,这里是grpc插件下的两个命令,compile是生成grpc的实体message的,compile-custom是生成grpc的service服务的,两个依次执行就能获得结果--><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins></build></project>

ok,至此我们完成了这个maven的配置,然后我们来测试一下效果。
我们来到idea的maven插件位置找到对应的goal。
在这里插入图片描述

然后先执行compile生成实体message,再执行compile-custom生成service。他会自己去扫这个目录下的proto文件然后生成的默认位置就是模块的target目录。然后把对应的生成类拷贝到我们的java类路径下。然后删除proto生成的文件即可。注意service和实体类不再一个目录下,但是都在generated-sources这个目录下。
而且生成的实体类名字为:HelloProto.java. 这个名字就是我们的那个外部类名字,这是他的规范。
生成的service类名字为:HelloServiceGrpc.java 这个名字就是我们的service名字加了一个Grpc,这是他的规范。

ok至此我们就完成了初始化类文件。后续我们就可以使用了,但是现在存在两个问题需要优化。
1、我们每次都得点两下maven插件,一个生成message,一个生成service才好,这样太麻烦了,我们实际上可以构建复合goal,可以在idea的maven插件组合多个gola,然后就能顺序执行了。这个我就不演示了。我还是执行两个命令吧,不太喜欢定制化。而且你可以用maven的组合命令执行,idea只是一个图形化了这个功能。

2、我们每次输出的java类都是在target目录下的。害得拷贝一次,我们可以在maven配置直接生成到我们要的目标java目录下。
我们在maven中添加outputDirectory配置。

<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><!--com.google.protobuf:protoc这个命令是生成grpc的实体message的,os.detected.classifier是maven的一个内置系统参数,用来获取本机操作系统类型,这里是获取本机的操作系统类型,然后根据操作系统类型来获取protoc的命令,无需你自己写死,这里maven会自己获取--><protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact><!--grpc-java--><pluginId>grpc-java</pluginId><!--io.grpc:protoc-gen-grpc-java这个命令是支持grpc的service服务的--><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.73.0:exe:${os.detected.classifier}</pluginArtifact><!--basedir就是当前模块的根目录,我们直接生成到我们的java目录下面去--><outputDirectory>${basedir}/src/main/java</outputDirectory></configuration><executions><execution><goals><!--goals是maven执行的命令,类似于clean或者install,这里是grpc插件下的两个命令,compile是生成grpc的实体message的,compile-custom是生成grpc的service服务的,两个依次执行就能获得结果--><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins>
</build>

然后我们删除掉现在的类,再执行一次。
在这里插入图片描述
我们发现service把前面的message覆盖了,第二次生成的结果会覆盖第一次,所以我们还要加一个配置。

<!--追加新的文件,而不是清除旧的文件-->
<clearOutputDirectory> false</clearOutputDirectory>

此时配置变成这样。

<plugins><plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.6.1</version><configuration><!--com.google.protobuf:protoc这个命令是生成grpc的实体message的,os.detected.classifier是maven的一个内置系统参数,用来获取本机操作系统类型,这里是获取本机的操作系统类型,然后根据操作系统类型来获取protoc的命令,无需你自己写死,这里maven会自己获取--><protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact><!--grpc-java--><pluginId>grpc-java</pluginId><!--io.grpc:protoc-gen-grpc-java这个命令是支持grpc的service服务的--><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.73.0:exe:${os.detected.classifier}</pluginArtifact><!--basedir就是当前模块的根目录,我们直接生成到我们的java目录下面去--><outputDirectory>${basedir}/src/main/java</outputDirectory><!--追加新的文件,而不是清除旧的文件--><clearOutputDirectory>false</clearOutputDirectory></configuration><executions><execution><goals><!--goals是maven执行的命令,类似于clean或者install,这里是grpc插件下的两个命令,compile是生成grpc的实体message的,compile-custom是生成grpc的service服务的,两个依次执行就能获得结果--><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin>
</plugins>

在这里插入图片描述
此时就没问题了,而且target也不生成了。ok。下面我们就可以正式开始编写rpc能力的业务代码了。

2、代码结构

我们现在已经完成了api模块的开发,而且我们也生成了对应的grpc的类。我们现在就来看看我们生成的这些类的内容。我们先来看实体消息message类。

2.1、实体类message

在这里插入图片描述
我们在定义message的时候,就说了我们的实体类是被管理在一个外部类也就是我们这里的HelloProto里面的,我们使用的时候是以内部类的形式使用的HelloProto.HelloRequest以及HelloProto.HelloResponse这样的形式使用的。其余的是一些构建类和方法,我们先不说。

2.2、服务类service

而我们的服务类定义的时候名字是HelloService,最终生成的结果类为HelloServiceGrpc,可见其实就是在后面加了一个Grpc,而且也是都是内部类的形式,我们主要使用的就是这些内部类。我们之前在thrift的时候使用grpc的业务类其实是要实现他的接口覆盖他的方法实现自己的业务。
在这里插入图片描述
在grpc这里我们要实现的那个自己的业务类其实是HelloServiceImplBase这个内部类,我们需要在他的bindService里面书写我们的业务内容。他的命名方式就是我们声明的HelloServiceI后面加了一个ImplBase,这个和当初thrift的IFace接口一样。
其余的那些以Stub结尾的类其实就是生成的客户端发起远程rpc调用的接口类,不同的stub表示不同的rpc方法。
HelloServiceFutureStub这一看就是异步调用,返回Future。
HelloServiceBlockingStub这一看就是阻塞调用。其余等等,我们后面操作的时候会看到的。

ok至此我们就完成了api模块的实现,下面我们来编写client和server模块的代码,实现基于grpc的一个rpc调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91661.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91661.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IOS 18下openURL 失效问题

突然有一天有玩家反馈说应用打开外部连接打不开了&#xff0c;于是查了一下&#xff0c;报错&#xff1a;BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(_:) needs to migrate to the non-deprecated UIApplication.open(_:options:completionHandler:). Force…

前端面试题(React 与 Vue)

目录 一、React 函数组件 Fiber架构 组件重新渲染 组件通信 为什么不能在if中使用hook useEffect与useLayoutEffect区别 性能优化hooks 受控组件与非受控组件 redux与zustand区别 二、Vue vue2与vue3区别 生命周期 computed与watch区别 v-if与v-show区别 v-mod…

大模型格式

目录 大模型格式&#xff1a; ollma 可以加载gguf ChatGPT 说&#xff1a; &#x1f50d; 什么是 GGUF&#xff1f; 大模型格式&#xff1a; Ollama 模型格式只能运行已打包成 .gguf 格式的模型&#xff0c;或通过其 Modelfile 方式构建 ModelScope 模型格式大多使用 Hug…

数据结构 栈(1)

1. 栈的概念和结构之前几篇我们分别讲解了顺序表和单链表的内容&#xff0c;今天我们又来学习一个新的关于数据结构的内容--- 栈 。栈&#xff1a;栈也属于线性表 , 但它是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一…

【Android代码】绘本翻页时通过AI识别,自动通过手机/pad朗读绘本

核心功能&#xff1a; 打开摄像头&#xff08;可支持外接摄像头&#xff09;检测翻页&#xff08;后续考虑添加图像差异算法&#xff09;拍照后用 识图自动用 TextToSpeech 朗读文字内容 &#x1f4cc; 说明&#xff1a;使用了 CameraX&#xff08;Android Jetpack&#xff09;…

园区IPv6规划与部署

​今天我将围绕“园区IPv6规划与部署”这一主题&#xff0c;结合行业趋势、技术难点和实际案例&#xff0c;与大家分享一套可落地的规划方法论。​在开始前&#xff0c;我想先问大家一个问题&#xff1a;​如果现在让你给一个新建园区设计网络&#xff0c;你会优先考虑IPv4还是…

mingw11.2+opencv4.12 cmake contrib编译

第一次Configure之后&#xff0c;会出现不少错误&#xff0c;主要是因为文件没办法正常下载引起的,因为之前编译过vs2022 ,缓存里面有应该下载的文件了&#xff0c;所以这次没有错误&#xff0c;如果你第一次Configure有下载错误&#xff0c;可以下载以下的文件飞书 Docs Link:…

免费MCP服务:Excel CSV 转 JSON MCP by WTSolutions 文档

简介 Excel 转 JSON MCP&#xff08;模型上下文协议&#xff09;提供了一个标准化接口&#xff0c;用于通过模型上下文协议将 Excel 和 CSV 数据转换为 JSON 格式。此 MCP 实现提供了两个专门用于数据转换的工具&#xff1a; excel_to_json_mcp_from_data&#xff1a;转换制表…

应用集成体系深度解析:从数据互通到流程协同

一、应用集成核心概念框架 #mermaid-svg-0V3XAJsofKi2qCa7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0V3XAJsofKi2qCa7 .error-icon{fill:#552222;}#mermaid-svg-0V3XAJsofKi2qCa7 .error-text{fill:#552222;s…

深入解析 AWS RDS Proxy

在当今微服务架构与无服务器计算快速发展的背景下&#xff0c;数据库连接成为许多应用系统的性能瓶颈。传统RDS实例在处理大量短连接请求时&#xff0c;往往面临连接资源耗尽、连接建立耗时过高等问题。为了解决这一挑战&#xff0c;AWS 推出了 RDS Proxy 服务&#xff0c;通过…

深度剖析 TDMQ RabbitMQ 版经典队列底层存储机制

导语 RabbitMQ 作为开源消息队列的标杆产品&#xff0c;凭借灵活的路由机制与高可用设计&#xff0c;支撑着海量业务场景的消息流转。而经典队列&#xff08;Classic Queue&#xff09; 作为 RabbitMQ 最基础、应用最广泛的队列类型&#xff0c;其底层存储机制直接决定了消息处…

Spring AI开发智能客服(Tool calling)

文章目录前言1 思路分析2 工程结构搭建1_数据库表2_引入依赖3_基础代码3 定义 Tool1_分析查询条件2_定义Function4 系统提示词5 配置ChatClient6 编写Controller7 测试8 Tool calling 底层组件1_ToolCallback2_ToolDefinition3_ToolCallingManager4_ResultConverter5_ToolConte…

设计模式笔记_结构型_适配器模式

1.适配器模式介绍适配器模式是一种结构型设计模式&#xff0c;它允许不兼容的接口协同工作。适配器模式的核心思想是将一个类的接口转换成客户期望的另一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的类可以一起工作。你可以将其想象成一个“转换插头”——假设你…

事务隔离:从锁实现到MVCC实现

文章目录事务隔离&#xff1a;从锁实现到MVCC实现事务四大特性事务隔离级别锁实现概念实现事务隔离MVCC实现当前读与快照读实现事务隔离Read View总结事务隔离&#xff1a;从锁实现到MVCC实现 面试的时候被面试官问到&#xff1a;你这个项目为什么使用了可重复读而不选择读已提…

小架构step系列18:工具

1 概述 在写代码的时候&#xff0c;有很多通用的、与业务无关逻辑&#xff0c;这些一般写成工具类方法。这些工具类方法慢慢地被积累起来&#xff0c;变成了开源包&#xff0c;可以直接使用开源包&#xff0c;而不是自己再花时间来重复造这些轮子。 这些工具类的开源包比较多…

网络、CentOS 系统、数据库面试知识点总结

文章目录Linux CentOS 面试知识点整理速查复习✅ 一、Linux 高频面试题✅ 二、MySQL 高频面试题✅ 三、计算机网络&#xff08;OSI四层模型&#xff09;高频面试题&#x1f517; 链路层&#xff08;Link Layer&#xff09;&#x1f310; 网络层&#xff08;Internet Layer&…

Vue (Official) v3.0.2 新特性 为非类npm环境引入 globalTypesPath 选项

目录 前言 报错信息 原因 解决方案 总结 前言 在早上更新了vscode后&#xff0c;发现自己 uni-app 项目的 .vue文件 的 template 标签都出现了报错。定位到了问题是因为 Vue (Official) 插件更新导致的&#xff0c;重装了插件的上一个小版本&#xff0c;报错消失&#xff…

程序可能的输出

#include "csapp.h"int main() {int x 3;if (Fork() ! 0)printf("x%d\n", x);printf("x%d\n", --x);exit(0); }分析&#xff1a;父进程先执行printf("x%d\n", x); 输出x4。后执行 printf("x%d\n", --x);输出x3。子进程只执…

2025年UDP应用抗洪指南:从T级清洗到AI免疫,实战防御UDP洪水攻击

一次未防护的UDP暴露&#xff0c;可能让日活百万的应用瞬间瘫痪&#xff0c;损失超千万2025年&#xff0c;随着物联网僵尸网络规模指数级增长及AI驱动的自适应攻击工具泛滥&#xff0c;UDP洪水攻击峰值已突破8Tbps&#xff0c;单次攻击成本却降至50元以下。更致命的是&#xff…

centos7安装MySQL8.4手册

目录前言一、首先更新插件&#xff0c;并查看当前系统版本二、安装步骤1、创建mysql目录2、安装rpm包3、安装 mysql-community-server4、启动MySQL服务5、查看MySQL状态6、设置开机自启动三、查看默认密码四、登录mysql五、修改密码六、开启远程访问1. 修改 MySQL 配置文件2. 重…