OpenFeign的简单介绍和功能实操
前言
本文主要做一下OpenFeign的简单介绍和功能实操,实操主要是OpenFeign的超时和重试,在阅读本文章前,请完成《Nacos 注册中心介绍与实操》内的Nacos多模块生产消费者项目
什么是OpenFeign
OpenFeign全名Spring Cloud OpenFeign,是SpringCloud开发团队基于Feign开发的框架,声明式Web服务客户端
- Feign是一种声明式、模板化的HTTP客户端,可用于调用HTTP API实现微服务之间的远程服务调用。它的特点是使用少量的配置定义服务客户端接口,可以实现简单和可重用的RPC调用。
- Feign实现了声明式调用,允许程序员只需定义接口并作出一些小的注释,就可以实现一个完整的客户端,从而开发简单,潜在的问题可以被检测出来,程序的可维护性和可读性也更好。
- Feign支持动态服务发现,可以在接口地址变更或服务重新发布后实现自动切换,避免了因配置变更导致的杂乱代码,更具有拓展性。
- Feign解决了服务之间依赖过于厚实的一种解决方案,相比REST或RPC,Feign可以减少大量不必要的代码。它基于可插拔修改的过滤链,默认支持多种HTTP请求和响应。
OpenFeign功能升级
OpenFeign在Feign的基础上提供了增强和扩展功能:
1、更好的集成SpringCloud其他组件:可以和服务发现、负载均衡组件一起使用
2、支持@FeignClient注解:OpenFeign引入该注解作为Feign客户端标识,可以方便地定义和使用远程服务调用
3、错误处理改进:OpenFeign对异常进行了增强,提供了更好的错误信息和异常处理机制,让开发者更为准备的判断错误所在。
如:OpenFeign提供的错误解码器(DefaultErrorDecoder)和回退策略(当服务端返回错误响应或请求失败时,OpenFeign会调用回退策略中的逻辑,提供一个默认的处理结果)。
4、更丰富的配置项:可以对Feign客户端进行配置,如超时时间、重传次数等
OpenFeign客户端
客户端与服务端的代码创建请前往Nacos 注册中心介绍与实操这篇文章上参考完成。
① 要使用OpenFeign需要使用@EnableFeignClients进行开启
@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}
}
② 编写接口服务,并使用@FeginClient(name=“xxxx”)来指定调用的服务站点
@Service
@FeignClient(name = "nacos-provider")
public interface UserService {@RequestMapping("/user/getInfo")public String getInfo(@RequestParam("name") String name);
}
③ 调用接口
@RestController
public class OrderController {private final UserService userService;@Autowiredpublic OrderController(UserService userService) {this.userService = userService;}@RequestMapping("/order")public String getInfo(){if(userService == null){return null;}return userService.getInfo(" Spring Cloud");}
}
④ 最终结果
OpenFeign中的超时重试机制
众所周知,在这个机器交互过程中,网络是最为复杂和难以控制的,而我们的微服务,讲究的就是一个高并发高可用,那么解决交互上存在的网络问题是十分必要的。
那么在OpenFeign中采用的方式就是超时重传,和TCP协议中的超时重传机制一样,链接或者消息在一定时间没有回应就会重新发送一次。
其实这很容易理解,就像我们在平时打电话,你沟通时,过一会对面都没有回应,你也会“喂,喂,听得见吗?”的消息确认。
开启超时重传机制
OpenFeign在默认情况下是不会开启这个机制的,需要我们人为去开启,那么开启需要通过下面两个步骤
- 配置超时重传
- 覆盖Retryer对象
1、配置
spring:cloud:openfeign:client:config:default: # 全局配置connect-timeout: 1000 # ms 链接超时时间read-timeout: 1000 # ms 读取超时时间
2、覆盖
在消费者目录下的config包下构建并注入IOC容器
@Configuration
public class RetryerConfig {@Beanpublic Retryer retryer(){return new Retryer.Default(1000, // 重试间隔时间1000, // 最大间隔时间3 // 最大重试次数);}
}
为了演示超时重传的触发,我们在生产者代码上使用Thread.sleep(2000)来让线程睡眠并且在进打印调用的时刻,这个睡眠时间超过配置中的read-time=1000
@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/getInfo")public String getInfo(@RequestParam("name") String name){System.out.println("provider.getInfo方法执行时间:"+ LocalDateTime.now());try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}return "producer" + name;}
}
生产者控制台信息:
客户端结果:
下面我们队这个结果进行一个简单的分析:
① 在consumer.getInfo()对provider.getInfo(“Spring Cloud”)进行调用的时候,由于provider.getInfo(“Spring Cloud”)中进行了睡眠,并且(sleep=2000ms) > (read-time=1000ms),所以引发了超时现象
② 超时后,由于我们设置了超时重试次数,那么OpenFeign将会按照这个Retryer中的规则进行重试,再次调用了provider.getInfo(“Spring Cloud”)方法,再次打印了方法执行时间
③ 在重试了一定次数后,我们的consumer.getInfo()都收不到回应,那么就会导致客户端获取信息失败,然后就报了500错误,任务是服务端出错了。
以上就是超时重传的简单实操,不过需要做一点简单的补充,可能有同学已经发现了,provider控制台打印的时间上有点和想象中的不一样
这里我们可以看到重试是两秒左右才进行的,而我们connect-time = 1000ms ||read-time=1000ms,都不为一秒啊,为什么是两秒才调用,而不是一秒呢????
如果有以上问题的同学,应该是忘记了Retryer中的一个参数,重试间隔时间=1000ms,这就以为则,如果我们出现了超时问题,具体重传的时间还需要加上重试间隔时间,才是真正调用服务的时间:(connect-time > 1000 || read-time > 1000)+ (period = 1000) == executetime
自定义超时重试机制
无敌的Spring Cloud肯定也思考到了灵活性,所以也提供了自定义超时重试机制的方式,分为下面两个步骤:
- 自定义超时重试机制(实现Retryer接口,重写continueOrPropagate);
- 设置配置文件
三种自定义超时重试类
- 固定时间间隔:也就是说,每次重试开始时间间隔一样,例如:上面的实操例子
- 增长性间隔:例如:第一次超时重试间隔1秒,第二次2秒,第三次3秒,具体如何增长看业务实现的增长函数
- 随机时间间隔:重试间隔在一定范围内随机
自定义超时类实操
说明
:这个实操基于第一种自定义超时类来实现,不需要注入IOC
1、自定义超时重试机制
public class MyRetryConfig implements Retryer {private final int maxAttempts; // 最大尝试次数private final long intervalTime;// 重试间隔时间private int attempt; // 当前尝试次数public MyRetryConfig() {this.maxAttempts = 3;this.intervalTime = 1000;this.attempt = 0;}public MyRetryConfig(int maxAttempts, long intervalTime) {this.maxAttempts = 3;this.intervalTime = 1000;this.attempt = 0;}@Overridepublic void continueOrPropagate(RetryableException e) {// 假如当前尝试次数超过了最大尝试次数就抛出异常if(++this.attempt > this.maxAttempts){throw e;}long curInterval = this.intervalTime;// 打印日志System.out.println(LocalDateTime.now() + "执行了一次重试");try {Thread.sleep(curInterval);} catch (InterruptedException ex) {throw new RuntimeException(ex);}}/*** 克隆(创建独立的实例)* @return*/@Overridepublic Retryer clone() {// 克隆的间隔时间和重试次数当然要和被克隆对象一直,所以有参构造更为正确return new MyRetryConfig(maxAttempts, intervalTime);}
}
2、将自定义超时重传类声明到yml配置文件中
关键词:retryer: com.example.consumer.config.MyRetryConfig
spring:application:# 服务注册站点name: nacos-consumer #命名不能使用‘_’,早期SpringCloud不支持cloud:nacos:# Nacos认证信息discovery:username: nacospassword: nacos# Nacos 服务发现与注册配置,其中子属性server-addr指定Nacos服务器主机和端口server-addr: localhost:8848namespace: public # 注册到nacos的指定namespace,默认publicregister-enabled: falseopenfeign:client:config:default: # 全局配置connect-timeout: 1000 # ms 链接超时时间read-timeout: 1000 # ms 读取超时时间retryer: com.example.consumer.config.MyRetryConfig
server:port: 8080
测试结果:
超时重试底层原理
超时原理
超时原理其实很简单,OpenFeign超时底层实现是通过配置HTTP客户端来实现,通过你对配置文件的connect-timeout和read-timeout来底层进行设置
OpenFeign底层的HTTP客户端可以使用Apache HttpClient或者OK HttpClient来实现,默认是ApacheHttpClient
重试原理
通过观察OpenFeign 的源码实现就可以了解重试功能的底层实现,它的源码在 SynchronousMethodHandler 的 invoke 方法下,如下所示
**public Object invoke(Object[] argv) throws Throwable {RequestTemplate template = this.buildTemplateFromArgs.create(argv);Request.Options options = this.findOptions(argv);Retryer retryer = this.retryer.clone();// 一直重试while(true) {try {// 如果得到结果就return退出循环return this.executeAndDecode(template, options);} catch (RetryableException var9) {RetryableException e = var9;try {// 如果遇到异常则调用Retryer的continueOrPropagateretryer.continueOrPropagate(e);} catch (RetryableException var8) {Throwable cause = var8.getCause();if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {throw cause;}throw var8;}if (this.logLevel != Level.NONE) {this.logger.logRetry(this.metadata.configKey(), this.logLevel);}}}}
Retryer的continueOrPropagate方法底层实现:
public void continueOrPropagate(RetryableException e) {if (this.attempt++ >= this.maxAttempts) {throw e;} else {long interval;if (e.retryAfter() != null) {interval = e.retryAfter().getTime() - this.currentTimeMillis();if (interval > this.maxPeriod) {interval = this.maxPeriod;}if (interval < 0L) {return;}} else {interval = this.nextMaxInterval();}try {Thread.sleep(interval);} catch (InterruptedException var5) {Thread.currentThread().interrupt();throw e;}this.sleptForMillis += interval;}}
补充说明
OpenFeign实现原理
1.注解
2.动态代理实现—>功能扩展
3.RestTemplate发送HTTP请求
4.HTTP框架来实现Web请求->Apache HttpClient或者OK HttpClient
相关文章:

OpenFeign的简单介绍和功能实操
前言 本文主要做一下OpenFeign的简单介绍和功能实操,实操主要是OpenFeign的超时和重试,在阅读本文章前,请完成《Nacos 注册中心介绍与实操》内的Nacos多模块生产消费者项目 什么是OpenFeign OpenFeign全名Spring Cloud OpenFeignÿ…...

webpack 高级
高级配置就是要进行 webpack 优化,让代码在编译、运行时性能更好 主要从以下角度去优化: 1、提升开发体验 2、提升打包构建速度 3、减少代码体积 4、优化代码运行性能 一、提升体验 1、SourceMap 为什么 打包出来的所有css和js合并成了一个文件&#…...

OLE DB 访问接口所需的(最大)数据长度为 18,但返回的数据长度为 6。
sqlserver查询oracle链接服务器视图,报错 给最终返回的字符串进行类型转换,字符串大小按返回值最大的那个oracle源本字段类型长度 aaaaaa AS yljgbmcast(aaaaaa AS varchar(10)) AS yljgbm...

oracle (9)Storage Relationship Strut
目录 一、基础知识 1、数据库逻辑结构图 2、Types of Segments 段的类型 3、Storage Clause Precedence 存储条款的优先顺序 4、Extent Alloc & Dealloc 区的范围分配和取消分配 5、 Used and Free Extents 使用和自由区 6、Database Block 数据库块 7、Multiple B…...

React 项目结构小结
React 项目结构小结 简单的记录一下目前 React 项目用的依赖和实现 摸索了大半年了大概构建一套用起来还算轻松的体系……?基本上应该是说可以应对大部分的项目了 使用的依赖 目前项目还在 refactoring 的阶段,所以乱得很,这里是新建一个…...

4.网络之TCP
TCP协议(传输层) 文章目录 TCP协议(传输层)1. TCP报文格式2. TCP相关机制2.1 确认应答机制2.2 超时重传机制2.3 连接管理机制(重点)2.3.1 三次握手2.3.2 四次挥手 2.4 滑动窗口机制2.5 流量控制机制2.6 拥塞控制机制2.7 延迟应答机制2.8 捎带应答机制 3.…...

电池原理与分类
1 电池基础知识 电池目前大量应用于我们的生活中,主要包括3C消费类、动力类、储能类。 图1 电池应用方向 备注:3C指的是计算机(Computer )、通讯(Communication)消费类电子产品(Consumer Electronic)三类…...

Mongoose 开源库--Filesystem(文件系统)使用笔记
一、相关API Mongoose 开源库中也包含 文件系统 相关的 API,如下: 文件虚拟层: struct mg_fs {int (*st)(const char *path, size_t *size, time_t *mtime); // stat filevoid (*ls)(const char *path, void (*fn)(const char *, void *), v…...

新兴初创企业参展招募
一般来说,创业公司的生存率较低,失败率较高。根据不同的数据来源,创业公司的失败率高达 80%-90%。据统计,在中国每年新注册的企业数量超过 100 万家,但能够存活到 5 年以上的企业不足 7%,10 年以上不足 2%。…...

【Linux】Nginx安装使用负载均衡及动静分离(前后端项目部署),前端项目打包
一、Nginx导言 1、引言 Nginx 是一款高性能的 Web 服务器和反向代理服务器,也可以充当负载均衡器、HTTP 缓存和安全防护设备。它的特点是内存占用小、稳定性高、并发性强、易于扩展,因此在互联网领域得到了广泛的使用。 总结出以下三点: 负载均衡&#…...

银行和金融企业为何青睐这8款项目管理工具
银行、金融行业中主流的8款项目管理系统:1.PingCode;2.Worktile;3.Microsoft Project;4.Jira by Atlassian;5.Asana;6.Trello;7.Wrike;8.Teambition。 银行和金融性质的公司在项目管…...
一分钟理解npm run dev 和 npm run serve
前端开发过程中运行Vue项目的时候,有时候使用npm run serve命令可以启动项目,有时候却会报错;有时候使用npm run dev命令可以启动项目,有时候却也会报错。是什么原因造成这种情况呢,原因在于Vue脚手架版本的问题&#…...

HTTP 协议请求头 If-Match、If-None-Match 和 ETag
概述 在 HTTP 协议中,请求头 If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since、If-Range 主要是为了解决浏览器缓存数据而定义的请求头标准,按照协议规范正确的判断和使用这几个请求头,可以更精准的处理浏览器缓存&#x…...
DAY42 1049.最后一块石头的重量II + 494.目标和 + 474.一和零
1049.最后一块石头的重量II 题目要求:有一堆石头,每块石头的重量都是正整数。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x < y。那么粉碎的可能结果如下: …...

uniapp原生插件之安卓华为统一扫码HMS Scan Kit
插件介绍 华为统一扫码服务(Scan Kit)提供便捷的条形码和二维码扫描、解析、生成能力 插件地址 安卓华为统一扫码HMS Scan Kit - DCloud 插件市场 超级福利 uniapp 插件购买超级福利 详细使用文档 详细使用文档 插件申请权限 android.permi…...

数模国赛——多波束测线问题模型建立研究分析
第一次参加数模国赛,太菜了~~~~意难平 问题一 画出与测线方向垂直的平面和海底坡面的交线构成一条与水平面夹角为𝐀的斜线的情况下的示意图进行分析,将覆盖宽度分为左覆盖宽度和右覆盖宽度,求出它们与海水深度和𝐀、…...
[AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)
文章目录 一、简介二、服务请求报文定义肯定响应支持的NRC三、示例流程Step 1:Step 2:报文示例:Step 1:请求RequestDownload(0x34)服务Step 2:请求TransferData (0x36)服务,传输数据Step 3:请求RequestTransferExit(0x37)服务总结:三、示例代码37_req_transfer_e…...

vue+canvas实现横跨整个页面的动态的波浪线(贝塞尔曲线)
本来写这个特效 我打算用css实现的,结果是一波三折,我太难了,最终没能用css实现,转战了canvas来实现。来吧先看效果图 当然这个图的波浪高度、频率、位置、速度都是可调的,请根据自己的需求调整,如果你讲波浪什么的调大一下 还有有摆动的效果哦。 以下是完整代码 <…...

LeetCode算法题解| 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树
一、LeetCode 669. 修剪二叉搜索树 题目链接:669. 修剪二叉搜索树 题目描述: 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变…...

直播界很火的无线领夹麦克风快充方案 Type-C接口 PD快充+无线麦克风可同时进行
当前市场上流行一款很火的直播神器,无线领夹麦克风(MIC),应用于网红直播,网课教学,采访录音,视频录制,视频会议等等场景。 麦克风对我们来说并不陌生,而且品类有很多。随…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...

对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...

高抗扰度汽车光耦合器的特性
晶台光电推出的125℃光耦合器系列产品(包括KL357NU、KL3H7U和KL817U),专为高温环境下的汽车应用设计,具备以下核心优势和技术特点: 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计,确保在…...
13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析
LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...

作为点的对象CenterNet论文阅读
摘要 检测器将图像中的物体表示为轴对齐的边界框。大多数成功的目标检测方法都会枚举几乎完整的潜在目标位置列表,并对每一个位置进行分类。这种做法既浪费又低效,并且需要额外的后处理。在本文中,我们采取了不同的方法。我们将物体建模为单…...