【SpringCloud】使用OpenFeign进行微服务化改造

目录

    • 一、需求与背景
    • 二、OpenFeign 远程调用技术原理
    • 三、项目代码演示
      • 3.1 引入依赖
      • 3.2 实现@OpenFeign注解修饰接口
      • 3.3 指定 OpenFeign 远程调用接口的扫描路径
    • 四、OpenFeign 在日志中打印Request和Response
    • 五、OpenFeign 客户端超时配置
    • 六、使用 OpenFeign 实现服务降级
      • 6.1 实现降级
        • 6.1.1 引入依赖
        • 6.1.2 降级方式一
        • 6.1.2 降级方式二
      • 6.2 开启降级配置

一、需求与背景

  • 在分布式系统的场景下,大多数服务的拆分要进行微服务化,各微服务的内部不可能直接依赖其它微服务的实现,而是将该微服务内的POJO 类提取到一个公共模块,供其它的微服务进行依赖。
  • 为了让代码的职责更加明确,实现更加清晰,就需要将业务代码与框架使用的模版代码分离,让开发人员将精力集中到业务功能的实现上。

二、OpenFeign 远程调用技术原理

  • OpenFeign 是 Netflix 开源的一个项目,可以将远程的接口调用转换成本地调用的形式,简化了开发,并且做到了业务功能代码与框架模版代码分离的效果。
  • OpenFeign 的使用核心是基于 @FeignClient@EnableFeignClients 这2个注解。@EnableFeignClients 注解加在项目的启动类上,当项目在启动时,会扫描注解中指定的目录,会为所有使用了 @FeignClient 注解的接口创建一个动态代理对象,这些被创建的动态代理对象从属于@FeignClient注解所修饰的接口的实例,并把这些动态代理对象加载到 Spring 的 Bean 容器内,随后会被注入到需要进行远程调用的本地服务对象内。

三、项目代码演示

接下来使用一个积分项目进行演示。这个项目分为3个微服务:商品(goods)、用户(customer)、计算(caculation)。用户通过购买商品获取积分;不同的商品可能参加了不同的活动,有的商品不赠送积分;不同的用户等级可能通过购物获取的积分不同。

3.1 引入依赖

要使用 openFeign 组件,首先我们需要先引入相应的依赖。注意,使用openFeign 还需要引入loadBalancer 的依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

由于在父项目中已经引入了 spring-cloud-dependencies 的依赖,上述2个组件的版本号可通过版本仲裁确定,无需指定。

3.2 实现@OpenFeign注解修饰接口

实现OpenFeign组件的远程调用,首先需要实现@FeignClient 注解修饰的接口,该接口会将本地调用转化成远程的接口调用。

@FeignClient(value = "coin-goods-svc", path = "/goods")
public interface GoodsService {// 获取指定商品@GetMapping("/getGoods")GoodsInfo getGoods(@RequestParam("id") Long id);// 获取整个购物车内的商品@GetMapping("/getBatch")Map<Long, GoodsCart> getGoodsCart(@RequestParam("ids") Collection<Long> ids);
}

原来我们是直接通过 webclient 直接发起的远程接口调用,内容如下:

webClientBuilder.build().get().uri("http://coin-goods-svc/goods/getGoods?id=" + id).retrieve().bodyToMono(GoodsInfo.class).block();        

现在我们直接注入 GoodsService 并调取对应方法:

@Autowired
private GoodsService goodsService;public Integer getGoodsCoin(Long id) {// 忽略无关逻辑// 获取指定商品GoodsInfo goods = goodsService.getGoods(id);
}

现在我们不必再业务代码里面指定调用接口的URI 和 Method 了,做到了代码的职责分离。

3.3 指定 OpenFeign 远程调用接口的扫描路径

接下来,我们需要在微服务的启动类上加上 @EnableFeignClients 注解,这样服务启动时的,才会扫描指定目录下使用了 @FeignClient 注解的接口,并为其生成对应的动态代理实例。

// 省略其它注解
@EnableFeignClients(basePackages = {"com.fyup"})
public class CustomerApplication{// 忽略具体实现
}

我们也可以不指定具体的扫描路径,而是直接指定要进行代理的接口,不过这种方式在 OpenFeign 远程调用接口较多时会很麻烦,不具备扩展性,不符合开闭原则。

// 通过指定具体的远程调用接口
// 省略其它注解
@EnableFeignClients(clients = {GoodsService.class})
public class CustomerApplication{// 忽略具体实现
}

四、OpenFeign 在日志中打印Request和Response

OpenFeign 还提供了在日志中打印远程调用细节的功能,只需要开启相应配置,并向 Spring Bean 容器内注册对应的 Bean 即可。可打印的日志分为4个级别,这里贴一下源码的截图:

在这里插入图片描述
如上所示,如果我们选择 Level.FULL 级别,会打印完整的 Request 和 Response 的 Header、Body。
因为 OpenFeign 组件内的日志都是以 Debug 级别输出的,所以我们需要现将对应的远程调用接口的日志输出级别打开。

logging:level:com.fyup.coin.customer.feign.GoodsService: debug

因为要打印完整的 URL、Method、以及Request 和 Response 的 Header、Body 等信息,所以还需要在配置类中注入 Level.FULL 的 Bean。实现如下:

@Bean
Logger.Level feignLogger() {return Logger.Level.FULL;
}

五、OpenFeign 客户端超时配置

接口超时不响应会悬挂消费者请求,大量的请求超时未响应会给系统造成很大压力,在调用链路过长的情况下可能会在系统内部产生雪崩反应。
我们可以在Feign客户端的application.yml 文件中的 feign.client.config 配置项配置Feign 客户端远程调用的超时时间。feign.client.config.default 配置项配置全局的超时时间,通过 feign.client.config.${serviceName} 配置访问某个特定微服务的超时时间。 示例配置如下:

# 其它忽略
feign:client:config:# 全局超时配置default:connectTimeout: 1000readTimeout: 3000# 针对coin-goods-svc服务的超时配置coin-goods-svc:connectTimeout: 1000readTimeout: 2000

其中,connectTimeout 表示的是服务消费者与服务提供者建立远程连接的超时时间;
readTimeout 是指从发出请求开始,到服务端响应请求之前为客户端设置的请求超时时间。

六、使用 OpenFeign 实现服务降级

我们也可以使用 OpenFeign 组件实现服务降级,用法就是使用 @FeignClient 注解修饰远程调用接口时,使用 @FiegnClient 注解的 fallback 属性或者 fallbackFactory 属性指定降级方法的降级类即可。

6.1 实现降级

6.1.1 引入依赖

因为OpenFeign 实现服务降级依赖于 hystrix ,因此我们需要先引入hystrix 依赖如下:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><version>2.2.9.RELEASE</version><exclusions><exclusion><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-netflix-ribbon</artifactId></exclusion></exclusions>
</dependency>
6.1.2 降级方式一

下面实现了一个降级类示例,该降级类是通过 @FiegnClient 注解的 fallback 属性来指定的:

@Slf4j
@Component
public class GoodsServiceDowngrade implements GoodsService {// 获取指定商品@Overridepublic GoodsInfo getGoods(Long id) {// 对应的远程调用方法执行失败后会调用该方法,根据业务情况自行设计实现细节,此处仅打印日志log.info("fallback method in getGoods.");return null;}// 获取整个购物车内的商品@Overridepublic Map<Long, GoodsCart> getGoodsCart(Collection<Long> ids) {// 对应的远程调用方法执行失败后会调用该方法,根据业务情况自行设计实现细节,此处仅打印日志log.info("fallback method in getGoodsCart.");return null;}
}

接下来在远程调用接口内指定降级类:

@FeignClient(value = "coin-goods-svc", path = "/goods", fallback=GoodsServiceDowngrade.class)
public interface GoodsService {// 获取指定商品@GetMapping("/getGoods")GoodsInfo getGoods(@RequestParam("id") Long id);// 获取整个购物车内的商品@GetMapping("/getBatch")Map<Long, GoodsCart> getGoodsCart(@RequestParam("ids") Collection<Long> ids);
}
6.1.2 降级方式二

下面实现的降级类,是通过 @FiegnClient 注解的 fallbackFactory 属性来指定的,与上面不同的是,使用降级工厂处理降级可以获取到远程调用方法失败的原因。

@Slf4j
@Component
public class GoodsServiceDowngradeFactory implements FallbackFactory<GoodsService> {@Overridepublic GoodsService create(Throwable cause) {return new GoodsService() {@Overridepublic GoodsInfo getGoods(Long id) {// 根据业务情况自行设计实现细节,此处仅打印日志log.info("fallback method in getGoods.", cause);return null;}@Overridepublic Map<Long, GoodsCart> getGoodsCart(Collection<Long> ids) {log.info("fallback method in getGoodsCart.", cause);return null;}};}
}

下面我们在@FeignClient 注解修饰的远程调用接口内使用我们实现的降级工厂:

@FeignClient(value = "coin-goods-svc", path = "/goods", fallbackFactory=GoodsServiceDowngradeFactory.class)
public interface GoodsService {// 获取指定商品@GetMapping("/getGoods")GoodsInfo getGoods(@RequestParam("id") Long id);// 获取整个购物车内的商品@GetMapping("/getBatch")Map<Long, GoodsCart> getGoodsCart(@RequestParam("ids") Collection<Long> ids);
}

注意我们在使用的时候,降级类和降级工厂同时只能选择其中一种。

6.2 开启降级配置

最后一步,开启降级的配置开关feign.circuitbreaker.enabled: true,使代码生效。即在 application.yml 文件中,原来的配置中加上:

# 其它忽略
feign:client:config:# 全局超时配置default:connectTimeout: 1000readTimeout: 3000# 针对coin-goods-svc服务的超时配置coin-goods-svc:connectTimeout: 1000readTimeout: 2000circuitbreaker:enabled: true

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

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

相关文章

《区块链简易速速上手小册》第10章:区块链的未来与趋势(2024 最新版)

文章目录 10.1 区块链的未来展望10.1.1 基础知识10.1.2 主要案例&#xff1a;区块链在金融领域的发展10.1.3 拓展案例 1&#xff1a;区块链在供应链管理中的应用10.1.4 拓展案例 2&#xff1a;区块链在身份管理和隐私保护中的应用 10.2 新兴技术与区块链的融合10.2.1 基础知识1…

智能家居的网关新形态:Aqara 方舟智慧中枢 M3 体验

如果说在刚刚结束的 2023 年有哪些备受期待的智能家居产品&#xff0c;Aqara 方舟智慧中枢 M3 一定榜上有名&#xff0c;我的多位朋友也曾在装修过程中多次向我询问是否有这款产品的相关资讯&#xff1b;谁能想到自从在 2022 年 11 月首次亮相之后&#xff0c;这款产品一直等了…

vulhub靶机activemq环境下的CVE-2015-5254(ActiveMQ 反序列化漏洞)

影响范围 Apache ActiveMQ 5.x ~ Apache ActiveMQ 5.13.0 远程攻击者可以制作一个特殊的序列化 Java 消息服务 (JMS) ObjectMessage 对象&#xff0c;利用该漏洞执行任意代码。 漏洞搭建 没有特殊要求&#xff0c;请看 (3条消息) vulhub搭建方法_himobrinehacken的博客-CSD…

iOS图像处理----探索图片解压缩到渲染的全过程以及屏幕卡顿

一&#xff1a;图像成像过程 ①、将需要显示的图像&#xff0c;由CPU和GPU通过总线连接起来&#xff0c;在CPU中输出的位图经总线在合适的时机上传给GPU &#xff0c;GPU拿到位图做相应位图的图层渲染、纹理合成。 ②、将渲染后的结果&#xff0c;存储到帧缓存区&#xff0c;帧…

【脑电信号处理与特征提取】P7-贾会宾:基于EEG/MEG信号的大尺度脑功能网络分析

基于EEG/MEG信号的大尺度脑功能网络分析 Q: 什么是基于EEG/MEG信号的大尺度脑功能网络分析&#xff1f; A: 基于脑电图&#xff08;EEG&#xff09;或脑磁图&#xff08;MEG&#xff09;信号的大尺度脑功能网络分析是一种研究大脑活动的方法&#xff0c;旨在探索脑区之间的功能…

【JavaSE篇】——继承

目录 &#x1f393;继承 ✅为什么需要继承 ✅继承概念 ✅继承的语法 ✅父类成员访问 &#x1f6a9;子类中访问父类的成员变量 1. 子类和父类不存在同名成员变量的情况 2. 子类和父类成员变量同名 &#x1f6a9;子类中访问父类的成员方法 1. 成员方法名字不同 2. 成员…

SAM:基于 prompt 的通用图像分割模型

Paper: Kirillov A, Mintun E, Ravi N, et al. Segment anything[J]. arXiv preprint arXiv:2304.02643, 2023. Introduction: https://segment-anything.com/ Code: https://github.com/facebookresearch/segment-anything SAM 是 Meta AI 开发的一款基于 prompt 的通用视觉大…

100%涨点!2024最新卷积块创新方案盘点(附模块和代码)

在写论文时&#xff0c;设计高效、创新的卷积块可以显著提升模型的性能&#xff0c;保障工作的有效性和先进性。另外&#xff0c;合理利用卷积块还可以帮助我们提升实验结果、拓展研究的视野和应用场景&#xff0c;增加论文的创新点。因此&#xff0c;对于论文er来说&#xff0…

BSV区块链将凭借Teranode的创新在2024年大放异彩

​​发表时间&#xff1a;2024年1月15日 2024年1月15日&#xff0c;瑞士楚格 – BSV区块链协会研发团队今日官宣了Teranode的突破性功能&#xff0c;这些功能将显著提升BSV区块链网络的效率和速度。在不久的将来&#xff0c;BSV区块链的交易处理能力将达到每秒100万笔交易。 T…

粒子群优化算法

PSO算法 粒子群算法&#xff08;Particle,Swarm Optimization,PSO&#xff09;由Kennedy和Eberhart于1995年提出&#xff0c;算法模仿鸟群觅食行为对优化问题进行求解。 粒子群算法中每个粒子包含位置和速度两个属性&#xff0c;其中&#xff0c;位置代表了待求问题的一个候选…

安装GPU版本Pytorch(全网最详细过程)

目录 一、前言 二、安装CUDA 三、安装cuDNN 四、安装Anacanda 五、安装pytorch 六、总结 一、前言 最近因为需要安装GPU版本的Pytorch&#xff0c;所以自己在安装过程中也是想着写一篇博客&#xff0c;把整个过程记录下来&#xff0c;在整个过程中也遇到了不少的问题&a…

【开源】基于JAVA+Vue+SpringBoot的用户画像活动推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 兴趣标签模块2.3 活动档案模块2.4 活动报名模块2.5 活动留言模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 数据流程设计3.4 E-R图设计 四、系统展示五、核心代码5.1 查询兴趣标签5.2 查询活动推荐…

状态压缩 笔记

棋盘式的f[i][j]中表示状态的j可以是状态本身也可以是在合法状态state中的下标 用状态本身比较方便&#xff0c;用下标比较省空间 用下标的话可以开id[M]数组记录一下 蒙德里安的梦想 求把 NM的棋盘分割成若干个 12的长方形&#xff0c;有多少种方案。 例如当 N2&#xff0…

【Redis】一文搞懂redis的所有知识点

目录 1. 什么是Redis&#xff1f;它主要用来什么的&#xff1f; 2.说说Redis的基本数据结构类型 2.1 Redis 的五种基本数据类型​编辑 2.2 Redis 的三种特殊数据类型 3. Redis为什么这么快&#xff1f;​编辑 3.1 基于内存存储实现 3.2 高效的数据结构 3.3 合理的数据编…

新火种AI|哄哄大模型的火爆,给了普通人AI创业破局的关键

作者&#xff1a;一号 编辑&#xff1a;美美 人们似乎更喜欢把AI当做玩具&#xff0c;而非工具。 近日&#xff0c;一款名为哄哄模拟器的AI原生应用火了&#xff0c;一天之内就吸引了60万用户。 哄哄模拟器设置了多种情侣吵架场景&#xff0c;无论你是男是女&#xff0c;都…

光伏设计系统都具备哪些功能?

随着可再生能源的日益重要&#xff0c;光伏能源已成为我们能源结构中的重要组成部分。而光伏设计系统作为实现光伏能源高效利用的关键&#xff0c;其功能也日益丰富和多样化。本文将探讨光伏设计系统所具备的主要功能。 1.数据分析与模拟 光伏设计系统能够对大量的数据进行分…

【经典项目】Java小游戏 —— 贪吃蛇

一、需求分析 当提到贪吃蛇游戏时&#xff0c;通常是指一款经典的电子游戏&#xff0c;玩家通过操作一个蛇在屏幕上移动&#xff0c;目标是吃掉各种食物并尽量避免碰撞到自己的身体或游戏区域的边界。 贪吃蛇游戏最早出现在20世纪70年代末的个人电脑上&#xff0c;后来在各种游…

使用 Paimon + StarRocks 极速批流一体湖仓分析

摘要&#xff1a;本文整理自阿里云智能高级开发工程师王日宇&#xff0c;在 Flink Forward Asia 2023 流式湖仓&#xff08;二&#xff09;专场的分享。本篇内容主要分为以下四部分&#xff1a; StarRocksPaimon 湖仓分析的发展历程使用 StarRocksPaimon 进行湖仓分析主要场景和…

ONLYOFFICE是一站式协作免费开源办公神器

一、前言 众所周知&#xff0c;我们工作都离不开办公软件&#xff0c;一个好的办公软件可以大幅度提高工作效率&#xff0c;就目前市场而言&#xff0c;常见的办公软件有微软的 Microsoft Office 以及国产的 WPS Office&#xff0c;微软的 Microsoft Office是付费的&#xff0…

CANoe实际项目中文件夹的规划

本人&#xff0c;之前设计了一个CANoe工程&#xff0c;由于工程设计之初没有设计好文档的归纳分类&#xff0c;导致文件查找起来非常费劲。 为了避免以后出现文件混乱&#xff0c;不可查找的问题&#xff0c;故特此归纳说明。 建立工程时&#xff1a; 第1步就应该设计好文档…