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在默认情况下是不会开启这个机制的,需要我们人为去开启,那么开启需要通过下面两个步骤

  1. 配置超时重传
  2. 覆盖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肯定也思考到了灵活性,所以也提供了自定义超时重试机制的方式,分为下面两个步骤:

  1. 自定义超时重试机制(实现Retryer接口,重写continueOrPropagate);
  2. 设置配置文件

三种自定义超时重试类

  1. 固定时间间隔:也就是说,每次重试开始时间间隔一样,例如:上面的实操例子
  2. 增长性间隔:例如:第一次超时重试间隔1秒,第二次2秒,第三次3秒,具体如何增长看业务实现的增长函数
  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


END
希望对你有帮助

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

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

相关文章

树结构及其算法-二叉查找树

目录 树结构及其算法-二叉查找树 C代码 树结构及其算法-二叉查找树 二叉树在建立的过程中是根据“左子树 < 树根 < 右子树”的原则建立的&#xff0c;因此只需从树根出发比较键值即可&#xff0c;如果比树根大就往右&#xff0c;否则往左而下&#xff0c;直到相等就找…

基于OR-Tools的装箱问题模型求解(PythonAPI)

装箱问题 一、背包问题&#xff08;Knapsack problem&#xff09;1.1 0-1背包模型基于OR-Tools的0-1背包问题求解&#xff08;PythonAPI&#xff09;导入pywraplp库数据准备声明MIP求解器初始化决策变量初始化约束条件目标函数调用求解器打印结果 1.2 多重背包问题&#xff08;…

diffusers-Load pipelines,models,and schedulers

https://huggingface.co/docs/diffusers/using-diffusers/loadinghttps://huggingface.co/docs/diffusers/using-diffusers/loading 有一种简便的方法用于推理是至关重要的。扩散系统通常由多个组件组成&#xff0c;如parameterized model、tokenizers和schedulers&#xff0c…

SpringBoot整合自签名SSL证书,转变HTTPS安全访问(单向认证服务端)

前言 HTTP 具有相当优秀和方便的一面,然而 HTTP 并非只有好的一面&#xff0c;事物皆具两面性&#xff0c;它也是有不足之处的。例如&#xff1a; 通信使用明文&#xff08;不加密&#xff09;&#xff0c;内容可能会被窃听。不验证通信方的身份&#xff0c;因此有可能会遭遇…

多线程锁的升级原理是什么

在 Java 中&#xff0c;锁共有 4 种状态&#xff0c;级别从低到高依次为&#xff1a;无状态锁&#xff0c;偏向锁&#xff0c;轻量级锁和重量级锁状态&#xff0c;这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。 多线程锁锁升级过程 如下图所示 多线程锁的升级过程…

Ha-NeRF源码解读 train_mask_grid_sample

目录 背景&#xff1a; &#xff08;1&#xff09;Ha_NeRF论文解读 &#xff08;2&#xff09;Ha_NeRF源码复现 &#xff08;3&#xff09;train_mask_grid_sample.py 运行 train_mask_grid_sample.py解读 1 NeRFSystem 模块 2 forward()详解 3 模型训练tranining_st…

windows和docker环境下springboot整合gdal3.x

链接: gdal官网地址 gdal gdal的一个用c语言编写的库&#xff0c;用于处理地理信息相关的数据包括转换&#xff0c;识别数据&#xff0c;格式化数据以及解析 同时提供第三方语言的SDK包括python&#xff0c;java上述需要编译后使用 java是需要使用jni接口调用实现方法在wind…

SAR 系统基本原理

目录 1.真实孔径雷达 2.合成孔径雷达 本文由CSDN点云侠原创&#xff0c;爬虫网站请自重。 1.真实孔径雷达 RADAR 中文名称雷达&#xff0c;是 Radio Detection And Ranging&#xff08;无线电探测与定位&#xff09;的缩写。雷达发射机产生足够的电磁能量&#xff0c;经过收发…

人工智能-多层感知机

隐藏层 该模型通过单个仿射变换将我们的输入直接映射到输出&#xff0c;然后进行softmax操作。 如果我们的标签通过仿射变换后确实与我们的输入数据相关&#xff0c;那么这种方法确实足够了。 但是&#xff0c;仿射变换中的线性是一个很强的假设。 线性模型可能会出错 例如&…

MySQL8.0安装

安装过程 一.官网下载离线tar包二.安装MySQL三.验证 一.官网下载离线tar包 点击此处下载 链接&#xff1a;https://pan.baidu.com/s/1_p2esJax95Ow39wfgM_paw 提取码&#xff1a;g415 –来自百度网盘超级会员V2的分享 二.安装MySQL 1.上传到/usr/local目录下 2.解压安装包…

Tigger绕过激活锁/屏幕锁隐藏工具,支持登入iCloud有消息通知,支持iOS12.0-14.8.1。

绕过激活锁工具Tigger可以用来帮助因为忘记自己的ID或者密码而导致iPhone/iPad无法激活的工具来绕过自己的iPhone/iPad。工具支持Windows和Mac。 工具支持的功能&#xff1a; 1.Hello界面两网/三网/无基带/乱码绕过&#xff0c;可以完美重启&#xff0c;支持iCloud登录、有消…

香港高端人才通行证计划入围高校/全球百强大学综合名单公布!

香港高端人才通行证计划入围高校/全球百强大学综合名单公布&#xff01; 香港高才通计划希望吸引世界各地具备丰富工作经验及高学历的人才到香港探索机遇&#xff0c;这些高端人才包括高收入人士和在世界顶尖大学毕业的学生。 此计划并不适用于阿富汗、古巴、老挝、朝鲜、尼泊尔…

Python框架之Flask入门和视图

一、Flask入门和视图 需要安装Pycharm专业版 1. Flask简介 Python后端的2个主流框架 Flask 轻量级框架Django 重型框架 Flask是一个基于Python实现的web开发微框架 官方文档&#xff1a;https://flask.palletsprojects.com/ 中文文档&#xff1a;https://dormousehole.readthe…

WPF RelativeSource属性-目标对象类型易错

上一篇转载了RelativeSource的三种用法&#xff0c;其中第二种用法较常见&#xff0c;这里记录一下项目中曾经发生错误的地方&#xff0c;以防自己哪天忘记了&#xff0c;又犯了同样错误—WPF RelativeSource属性-CSDN博客 先回顾一下&#xff1a; 控件关联其父级容器的属性—…

物联网AI MicroPython传感器学习 之 QMC5883指南针罗盘传感器

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 QMC5883是一款表面贴装的集成了信号处理电路的三轴磁性传感器&#xff0c;应用场景主要包括罗盘、导航、无人机、机器人和手持设备等一些高精度的场合。 引脚定义 VCC&#xff1a;3V3&#…

在Qt中List View和List Widget的区别是什么,以及如何使用它们

2023年10月29日&#xff0c;周日晚上 目录 List View和List Widget的区别 如何使用QListView 如何使用QListWidget List View和List Widget的区别 在Qt中&#xff0c;QListView 和 QListWidget 是用于显示列表数据的两个常用控件&#xff0c;它们有一些区别和特点。 1. 数…

遥遥领先,免费开源的django4-vue3项目

星域后台管理系统前端介绍 &#x1f33f;项目简介 本项目前端基于当下流行且常用的vue3作为主要技术栈进行开发&#xff0c;融合了typescript和element-plus-ui&#xff0c;提供暗黑模式和白昼模式两种主题以及全屏切换&#xff0c;开发bug少&#xff0c;简单易学&#xff0c…

新手必看的Facebook广告投放基础思路

一、广告账号要求 如果您还没有Facebook账号&#xff0c;那么第一步是准备Facebook账号。 1、配置正确的网络环境 Facebook账号需要在稳定安全的网络环境中运行&#xff0c;否则很容易导致封禁。像我们常用的是Maskfog指纹浏览器&#xff0c;可以通过自定义浏览器指纹与为环…

私有网络的安全保障,WorkPlus Meet内网视频会议助力企业高效会议

在企业内部沟通与协作中&#xff0c;视频会议成为了一种必不可少的沟通方式。然而&#xff0c;传统的互联网视频会议往往受制于网络不稳定因素&#xff0c;给企业带来不便与困扰。WorkPlus Meet作为一款专注内网视频会议的软件&#xff0c;致力于为企业打造高效、稳定的内网视频…

Vue 3 响应式对象:ref 和 reactive 的使用和区别

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是尘缘&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f449;点击这里&#xff0c;就可以查看我的主页啦&#xff01;&#x1f447;&#x…