十六.SpringCloudAlibaba极简入门-整合Grpc代替OpenFeign

前言

他来了他来了,停了快2个月了终于又开始更新文章啦,这次带来的绝对是干货!!!。由于公司项目进行重构的时候考虑到,OpenFeign做为服务通信组件在高并发情况下有一定的性能瓶颈,所以将其替换为更高性能的通信组件Grpc,Grpc也是业界比较流行的服务通信组件,底层采用HTTP/2进行网络通信性能上高于基于Http/1.1的OpenFeign。 我将把Grpc的整合过程整理成文字分享给大家,喜欢请三连!!!,你的鼓励是我坚持下去的动力。

认识Grpc

OpenFeign基于 HTTP/1.1 协议。主要使用 JSON 或 XML 格式进行数据交换,这些格式更加人性化但分装臃肿效率较低。其主要用于 RESTful API 调用,支持声明式的 Web 服务客户端。

而 gRPC 是一个高性能、开源和通用的 RPC(远程过程调用)框架,基于 Protocol Buffers 序列化协议开发,在内部实现上,它采用了 HTTP/2 协议作为传输层协议的一部分来实现高效的双向流通信的能力等特性让它成为很多开发者热衷的工具库之一;gRPC 在处理大量数据时表现优异,适用于需要快速响应的应用场景,特别是在微服务架构中。

gRPC:

  • 强调高效的数据传输和低延迟通信。如金融交易、在线游戏等对延迟要求极高的场景
  • 适合构建高性能的分布式系统和服务间通信。在大规模微服务架构中,gRPC 可以显著提高系统的整体性能。
  • 支持流式传输,可以实现长连接和实时数据推送。

OpenFeign:

  • 注重简化开发者的代码编写工作。
  • 更加灵活,可以轻松地集成到现有的 Spring Boot 项目中。
  • 适用于轻量级的 RESTful API 调用。

总结来说,gRPC 和 OpenFeign 各有优势,选择哪种技术取决于具体的业务需求和技术栈。如果你需要高性能、低延迟的服务间通信,gRPC 是更好的选择;如果你希望简化开发流程并快速集成 RESTful API,OpenFeign 则更为合适。

案例实战

1.搭建工程

首先搭建一个SpringBoot父工程,父工程下分别有:grpc-api ,grpc-provider ,grpc-consumer 三个模块,分别代表:Grpc接口,生产者,消费者。父工程管理的依赖如下

<properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>21</java.version><skipTests>true</skipTests><spring-cloud.version>2023.0.1</spring-cloud.version><spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version><hutool.version>5.8.28</hutool.version><lombok.version>1.18.32</lombok.version></properties><!--SpringBoot依赖--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0</version></parent><dependencies><!--   常用工具类     --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency><!--SpringCloud 2020.* 禁用了bootstrap 而注册中心等配置文件需要 bootstrap.yml 为名的配置文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><!--注解配置器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

2.API模块

api模块需要导入grpc相关依赖,以及编写proto文件,我们根据proto文件自动生成Grpc的API接口文件,需要导入的依赖如下

<dependencies><!-- https://mvnrepository.com/artifact/net.devh/grpc-server-spring-boot-starter --><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><version>3.0.0.RELEASE</version></dependency><dependency><groupId>net.devh</groupId><artifactId>grpc-client-spring-boot-starter</artifactId><version>3.0.0.RELEASE</version></dependency><dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</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></plugins></build>

grpc-server-spring-boot-starter 和 grpc-client-spring-boot-starter 是Grpc的服务端和客户端的依赖,javax.annotation-api是对Grpc代码生成注解的支持,不导入该包会报错。然后导入了os-maven-plugin插件,以及 protobuf-maven-plugin 插件用来根据proto文件生成API代码的。

接着我们再API模块中main目录下创建一个proto目录,并创建一个文件User.proto,内容如下

syntax = "proto3";
/** 生产的代码合并到一个文件 **/
option java_multiple_files = false;
/** 生产代码输出的包路径 **/
option java_package = "cn.whale.api.User";/** API接口 **/
service UserApi {/** Grpc API 接口 **/rpc getById(GetUserReq) returns (GetUserRep) {}
}/** 响应对象 **/
message GetUserReq {/** Long 用户ID **/int64 id = 1;
}/** 结果对象 **/
message GetUserRep {/** Long 用户ID **/int64 id = 1;/** String 用户名字 **/string name = 2;
}

该文件是用来定义Grpc Api接口的,具体请看上面的注释,需要注意的是定义Protobuf 的 message 对象的字段类型可不能使用Java的类型,int64 对应Long, string 对应 String 具体请看:https://protobuf.com.cn/programming-guides/proto3/#specifying-types

编写好proto文件后,对api模块进行compile(IDEA 右侧 - api模块 - lifecycle - compile) ,然后会自动在API模块中生成Grpc相关的 API接口。
在这里插入图片描述

3.提供者服务

提供者服务首先是需要向Nacos注册(其他注册中心也行)的,然后导入api模块,编写Grpc的提供者服务,导入如下依赖

    <dependencies><!--grpc api 模块 --><dependency><groupId>cn.whale</groupId><artifactId>grpc-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--nacos服务发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--配置管理 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--grpc服务端依赖,api模块中引入了,这里其实可以不引--><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><version>3.0.0.RELEASE</version></dependency></dependencies>

接着对提供者服务进行配置,启动类正常写,没有什么新东西,bootstrap.yml配置如下

server:port: 8081 #tomcat 端口
grpc:server:port: 7071 #Grpc端口client: #Grpic客户端配置GLOBAL:negotiation-type: plaintext #协议类型,明文传输,也可以使用TLS进行加密传输,服务内部通信使用明文即可enable-keep-alive: truekeep-alive-without-calls: true
spring:application:name: grpc-provider #服务名cloud:nacos:discovery: #服务注册server-addr: nacos地址:8848config: #配置管理server-addr: ${spring.cloud.nacos.discovery.server-addr}file-extension: yml

接下来编写提供者服务的Grpc实现,创建一个类UserApiImpl 继承UserApiGrpc,具体如下

package cn.whale.grpc;import cn.whale.api.User.User;
import cn.whale.api.User.UserApiGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;/*** 标记Grpc提供者服务*/
@GrpcService
public class UserApiImpl extends UserApiGrpc.UserApiImplBase {/*** 接口方法实现* @param request :请求对象* @param responseObserver : 消息流对象,用来响应结果*/@Overridepublic void getById(User.GetUserReq request, StreamObserver<User.GetUserRep> responseObserver) {long id = request.getId();//TODO :去数据查询数据//封装结果数据User.GetUserRep userRep = User.GetUserRep.newBuilder().setId(id).setName("zs").build();//响应结果responseObserver.onNext(userRep);responseObserver.onCompleted();//异常情况//responseObserver.onError(exception);}
}
  • @GrpcService :Grpc的服务端注解
  • UserApiGrpc.UserApiImplBase :根据Proto自动生成的API接口
  • getById :我们定义的API接口方法,具体请看代码注释

到这里提供者就编写完成了,启动提供者服务,可以看到Grpc的端口

在这里插入图片描述

4.消费者服务

消费者服务也是要做服务注册,然后引入api模块,以及Grpc客户端依赖,具体如下

<dependencies><dependency><groupId>cn.whale</groupId><artifactId>grpc-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>net.devh</groupId><artifactId>grpc-client-spring-boot-starter</artifactId><version>3.0.0.RELEASE</version></dependency></dependencies>

编写启动类和创建bootstrap.yml文件

server:port: 8082
grpc:server:port: 7072client:GLOBAL:negotiation-type: plaintextenable-keep-alive: truekeep-alive-without-calls: true
spring:application:name: grpc-consumercloud:nacos:discovery:server-addr: nacos地址:8848config:server-addr: ${spring.cloud.nacos.discovery.server-addr}file-extension: yml

接着我们编写一个Conroller来实现和提供者的Grpc通信,代码如下

@RestController
@Slf4j
public class BusinessController {//指向提供者的服务名@GrpcClient(value = "grpc-provider")private UserApiGrpc.UserApiBlockingStub userApiBlockingStub;@GetMapping("/user")public String getUserById(){User.GetUserRep getUserRep = userApiBlockingStub.getById(User.GetUserReq.newBuilder().setId(1L).build());log.info("查询到用户信息,id =  {},name = {}",getUserRep.getId(),getUserRep.getName());return getUserRep.toString();}
}
  • @GrpcClient(value = “grpc-provider”) : 客户端注解,value指向了注册中心的提供者服务的名字,底层会自动进行负载均衡
  • UserApiGrpc.UserApiBlockingStub : Grpc 同步接口,它也支持异步调用UserApiGrpc.UserApiFutureStub

到这里消费者就编写完成了,启动消费者,通过浏览器访问/user,就可以拿到提供者返回的数据了

在这里插入图片描述

5.注意事项

最后说几个注意事项

  1. Grpc生成的对象只提供了Builder的方式设置值,所以没办法通过BeanUtils等工具进行对象之间的自动转换的,需要手动给Proto对象设置值。见生产者 User.GetUserRep
  2. 如果给Proto对象设置了空值会报错,所以在给对象设置值的时候建议先判断空值,然后给一个默认值,比如:String为null,就指定一个“”空字符串
  3. Grpc是无法返回一个null对象的,所以消费者端到底有没有拿到一个有效的结果不能直接用null来判断,需要取出具体的值来判断

就写到这把,剩下的坑大家自己去踩,如果文章对你有帮助请给个好评!!!

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

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

相关文章

MySQL库和表的操作

目录 一. 查看数据库 二. 创建数据库 三. 字符集和校验规则 四. 修改和删除数据库 4.1 数据库修改 4.2 数据库删除 五. 备份与恢复 5.1 备份 5.2 还原 5.3 注意事项 5.4 查看连接情况 六. 创建表 七. 查看表结构 八. 修改表 九. …

在Linux下配置gitee与Github的远程仓库

目录 前言 云服务器下载git 检测是否下载成功git Linux下配置gitee远程仓库 代码提交演示 git三板斧 Linux下配置Github远程仓库 最后的提醒 前言 那么本篇文章将是在&#xff0c;你已经创建了本地仓库的基础上&#xff0c;在Linux下配置gitee的远程仓库的步骤&#xff…

mini-lsm通关笔记Week2Day5

项目地址&#xff1a;https://github.com/skyzh/mini-lsm 个人实现地址&#xff1a;https://gitee.com/cnyuyang/mini-lsm Summary 在本章中&#xff0c;您将&#xff1a; 实现manifest文件的编解码。系统重启时从manifest文件中恢复。 要将测试用例复制到启动器代码中并运行…

ESP8266 STA模式TCP服务器 电脑手机网络调试助手

STA模式TCP服务器和手机电脑网络调试助手多连接

JMeter监听器与压测监控之Grafana

Grafana 是一个开源的度量分析和可视化套件&#xff0c;通常用于监控和观察系统和应用的性能。本文将指导你如何在 Kali Linux 上使用 Docker 来部署 Grafana 性能监控平台。 前提条件 Kali Linux&#xff1a;确保你已经安装了 Kali Linux。Docker&#xff1a;确保你的系统已…

基于AIRTEST和Jmeter、Postman的自动化测试框架

基于目前项目和团队技术升级&#xff0c;采用了UI自动化和接口自动化联动数据&#xff0c;进行相关测试活动&#xff0c;获得更好的测试质量和测试结果。

STM32设计防丢防摔智能行李箱-分享

目录 目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 1.电路图采用Altium Designer进行设计&#xff1a; 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 随着科技的不断发展&#xff0c;嵌入式系统、物联网技术、智能设备…

全面解析:HTML页面的加载全过程(一)--输入URL地址,与服务器建立连接

用户输入URL地址&#xff0c;与服务器建立连接 用户在浏览器地址栏输入一个URL 浏览器开始执行以下三步操作操作&#xff1a;url解析、DNS查询、TCP连接 第一步&#xff1a;URL解析 什么是URL&#xff1f; URL(Uniform Resource Locator&#xff0c;统一资源定位符)是互联网…

window 中安装 php 环境

window 中安装 php 环境 一、准备二、下载三、安装四、测试 一、准备 安装前需要安装 Apache &#xff0c;可以查看这篇博客。 二、下载 先到这里下载 这里选择版本为“VS16 x64 Thread Safe”&#xff0c;这个版本不要选择线程安全的&#xff0c;我试过&#xff0c;会缺少文…

Android Studio启动模拟器显示超时

问题报错: Timed out after 300seconds waiting for emulator to come online. 解决方案&#xff1a;升级Android Emulator 情况二&#xff1a;Error while waiting for device:AVD Pixel_4a_API_32 is already running. If that is not the case, delete the files at E:\An…

基于企业微信客户端设计一个文件下载与预览系统

在企业内部沟通与协作中&#xff0c;文件分享和管理是不可或缺的一部分。企业微信&#xff08;WeCom&#xff09;作为一款广泛应用于企业的沟通工具&#xff0c;提供了丰富的API接口和功能&#xff0c;帮助企业进行高效的团队协作。然而&#xff0c;随着文件交换和协作的日益增…

【算法一周目】滑动窗口(1)

目录 长度最小的子数组 解题思路 代码实现 无重复字符的最大字串 解题思路 代码实现 最大连续1的个数l l l 解题思路 代码实现 将x减到0的最小操作数 解题思路 代码实现 长度最小的子数组 题目链接&#xff1a;209. 长度最小的子数组题目描述&#xff1a; 给定一个…

硬件工程师零基础入门:一.电子设计安全要点与欧姆定律

硬件工程师零基础入门:一.电子设计安全要点与欧姆定律 第一节 电子设计安全要点第二节 欧姆定律 第一节 电子设计安全要点 电路小白最好先买直流稳压电源&#xff08;将高压转成低压直流电&#xff09;使用&#xff0c;尽量不要使用市电。 1.尽量不要捏住电源两端。 正确做法&a…

【C++】踏上C++学习之旅(九):深入“类和对象“世界,掌握编程的黄金法则(四)(包含四大默认成员函数的练习以及const对象)

文章目录 前言1. 实现Date类的构造函数2. 实现Date类的拷贝构造函数3. 实现Date类的赋值运算符重载4. 实现各Date对象之间的比较接口5. 实现Date对象的加减接口6. const成员7. 取地址及const取地址操作符重载 前言 在我们前面学习到了"类和对象"的四大默认成员函数(…

【含文档】基于django+Vue的荣誉证书管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 主要技术: django,mysql,vue 2.视频演示地址 3.功能 系统定义了三个角色&#xff1a;管理员和学生和教师。 管理员进…

学习QT第二天

QT6示例运行 运行一个Widgets程序运行一个QT Quick示例 工作太忙了&#xff0c;难得抽空学点东西。-_-||| 博客中有错误的地方&#xff0c;请各位道友及时指正&#xff0c;感谢&#xff01; 运行一个Widgets程序 在QT Creator的欢迎界面中&#xff0c;点击左侧的示例&#xf…

Flutter:AnimatedContainer实现导航侧边栏

导航侧边栏 import package:flutter/material.dart;void main() {runApp(const MyApp()); }class MyApp extends StatelessWidget {const MyApp({Key? key}):super(key: key);overrideWidget build(BuildContext context) {return const MaterialApp(title: Flutter Demo,home…

CI配置项,IT服务的关键要素

随着现今数字经济的不断发展&#xff0c;逐渐成熟的IT 基础设施已不再是简单的竞争优势&#xff0c;而已成为企业生存和发展的基石。然而&#xff0c;仅仅拥有强大的基础设施是不够的。为了保障 IT 服务的平稳运行和持续交付&#xff0c;企业还需要重点关注 IT 服务的核心构建模…

Spring Boot教程之四:在IntelliJ IDEA 以及 Eclips IDE中创建和配置Spring Boot

在本文中&#xff0c;我们将讨论如何使用IntelliJ IDEA 以及 Eclips IDE创建和设置 Spring Boot 项目。 Spring Boot建立在Spring 框架之上&#xff0c;包含 Spring 的所有功能。它现在越来越受到开发人员的青睐&#xff0c;因为它可以在极短的时间内快速构建生产环境&#xf…

我用豆包MarsCode IDE 做了一个 CSS 权重小组件

作者&#xff1a;夕水 查看效果 作为一个前端开发者&#xff0c;应该基本都会用VSCode来做开发&#xff0c;所以也应该见过如下这张图的效果: 以上悬浮面板分为2个部分展示内容。 <element class"hljs-attr">: 代表元素只有一个类名叫hljs-attr的类选择器&am…