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.mzph.cn/news/127974.shtml

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

相关文章

【计算机网络】路由器的工作原理

文章目录 输入端口处理和基于目的地转发交换结构输出端口处理排队问题参考资料 路由器的四个组件 输入端口(input port)&#xff1a;执行物理层功能&#xff08;input port 左边方框、output port 右边方框&#xff09;、数据链路层功能&#xff08;input/output port 中间方框…

043-第三代软件开发-第三方串口库使用

第三代软件开发-第三方串口库使用 文章目录 第三代软件开发-第三方串口库使用项目介绍第三方串口库使用示例代码 关键字&#xff1a; Qt、 Qml、 QextSerialPort、 QThread、 高频 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt…

多输入多输出 | Matlab实现k-means-LSTM(k均值聚类结合长短期记忆神经网络)多输入多输出组合预测

多输入多输出 | Matlab实现k-means-LSTM&#xff08;k均值聚类结合长短期记忆神经网络&#xff09;多输入多输出组合预测 目录 多输入多输出 | Matlab实现k-means-LSTM&#xff08;k均值聚类结合长短期记忆神经网络&#xff09;多输入多输出组合预测预测效果基本描述程序设计参…

[云原生1. ] 使用Docker-compose一键部署Wordpress平台

文章目录 1. Docker-compose概述1.1 简介1.2 docker-compose 的三大概念1.3 docker-compose配置模板文件常用的字段1.4 docker-compose 常用命令及格式 2. YAML 文件的详细介绍及编写注意事项2.1 简介2.2 yaml的特性2.2.1 语法特点2.2.2 数据结构2.2.3 引号的区别2.2.4 内置类型…

springboot配置https

SSL &#xff1a; secure socket layer 是一种加密协议&#xff0c;SSL主要用于保护数据在 客户端和服务器之间的传输&#xff0c;&#xff0c;防止未经授权的访问和窃取敏感信息 在腾讯云申请ssl证书 申请了之后在我的域名中&#xff0c;&#xff0c;解析 解析了之后&…

【驱动开发】注册字符设备使用gpio设备树节点控制led三盏灯的亮灭

注册字符设备使用gpio设备树节点控制led三盏灯的亮灭 设备树&#xff1a; 头文件&#xff1a; #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int OD…

物流小程序制作教程:从零到有,详细解析

随着互联网的快速发展&#xff0c;物流行业也逐渐实现了数字化转型。为了满足消费者对更加便捷、高效的服务需求&#xff0c;许多物流企业选择制作自己的小程序。本文将通过乔拓云网后台&#xff0c;带你轻松搭建物流小程序&#xff0c;主要分为以下几个部分&#xff1a; 一、进…

Microsoft 365 管理自动化

Microsoft 365 服务被大多数组织广泛使用&#xff0c;每天生成的数据量巨大。解决 Microsoft 365 中的问题可能非常困难&#xff0c;并且使用多个管理中心来保护组织变得复杂。本机控制台还缺少某些批量管理任务、全面的审计报告和基于角色的精细访问控制。 Microsoft 360 管理…

云计算的思想、突破、产业实践

文章目录 &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。&#x1f30e;跑过十五…

【C++项目】高并发内存池项目第八讲 项目总结和面试问题分享

项目总结面试分享 1.项目总结1.1优点1.2不足1.3面试常见问题 2.面试分享项目部分C语法部分 项目源代码&#xff1a;高并发内存池 1.项目总结 1.1优点 增加动态申请的效率减少陷入内核的次数减少系统内存碎片提升内存使用率尽量减少锁竞争应用于多核多线程场景 1.2不足 当前…

万字解析设计模式之原型模式与建造者模式

一、原型模式 1.1概述 原型模式是一种创建型设计模式&#xff0c;其目的是使用已有对象作为原型来创建新的对象。原型模式的核心是克隆&#xff0c;即通过复制已有对象来创建新对象&#xff0c;而不是通过创建新对象的过程中独立地分配和初始化所有需要的资源。这种方式可以节…

shell script 案例二

需求&#xff0c;运行程序&#xff0c;用户输入firstname&#xff0c;回车&#xff0c;再次提示输入lastname&#xff0c;然后回车&#xff0c;屏幕打印fullname信息 注意&#xff1a;前期写程序要注意规范&#xff0c;方便以后自己写多了回头看可以看的懂&#xff0c;程序代码…

如何在麒麟上安装 ONLYOFFICE 桌面编辑器

我们很高兴地告诉大家&#xff0c;ONLYOFFICE 桌面编辑器现已上架麒麟软件商店。请阅读下文了解详情。 关于麒麟 麒麟是一款国产操作系统&#xff0c;主要是为了满足中国市场的需求和偏好而设计的。 它能够与各种硬件平台和软件应用程序的广泛兼容&#xff0c;因而受到认可。…

路由器如何设置IP地址

IP地址是计算机网络中的关键元素&#xff0c;用于标识和定位设备和主机。在家庭或办公室网络中&#xff0c;路由器起到了连接内部设备和外部互联网的关键作用。为了使网络正常运行&#xff0c;需要正确设置路由器的IP地址。本文将介绍如何设置路由器的IP地址&#xff0c;以确保…

性能测试 —— Jmeter日志查看与分析

一、Jmeter日志概览 Jmeter日志文件保存在bin目录中&#xff0c;名称为jmeter.log。我们可以在面板中直接察看日志&#xff0c;点击右上角黄色标志物可以打开日志面板&#xff0c;再次点击收起 另外&#xff0c;Jmeter可以很方便地设置日志输出级别&#xff1a; 通过这种方式修…

腾讯云轻量级服务器哪个镜像比较好?

腾讯云轻量应用服务器镜像是什么&#xff1f;镜像就是操作系统&#xff0c;轻量服务器镜像系统怎么选择&#xff1f;如果是用来搭建网站腾讯云百科txybk.com建议选择选择宝塔Linux面板腾讯云专享版&#xff0c;镜像系统根据实际使用来选择&#xff0c;腾讯云百科来详细说下腾讯…

使用shardingJDBC中的雪花算法生成id

常用ID解决方案 数据库自增id 依靠数据库系统的功能实现&#xff0c;但是未来扩容麻烦主从切换时的不⼀致可能会导致重复发号性能瓶颈存在单台sql上 UUID 性能非常高&#xff0c;没有网络消耗无序的字符串&#xff0c;不具备趋势自增特性UUID太长&#xff0c;不易于存储&am…

Django开发实例总结(入门级、4.2.6、详细)

目录 概述 Django的核心组件包括 Django的项目结构 创建工程&#xff08;4.2.6&#xff09; 实例一&#xff1a;Hello world 实例二&#xff1a;访问一个自定义主页 实例三&#xff1a;通过登录跳转到主页 实例四&#xff1a;主页添加静态文件&#xff0c;包含js、css、…

Android开发笔记(三)—Activity篇

活动组件Activity 启动和结束生命周期启动模式信息传递Intent显式Intent隐式Intent 向下一个Activity发送数据向上一个Activity返回数据 附加信息利用资源文件配置字符串利用元数据传递配置信息给应用页面注册快捷方式 启动和结束 &#xff08;1&#xff09;从当前页面跳到新页…

0032Java程序设计-基于JavaEE的智能化酒店点餐收款系统的设计与实现论文

文章目录 摘 要目录系统设计开发环境 摘 要 酒店点餐收款系统是为了实现酒店餐饮自动化管理而设计的&#xff0c;它完全取代了原来酒店餐饮管理一直使用的人工处理的工作方式&#xff0c;并且避免了由于管理人员的工作疏忽以及管理质量问题所造成的各种错误&#xff0c;为及时…