spring boot 2.4.x 之前版本(对应spring-cloud-openfeign 3.0.0之前版本)feign请求异常逻辑

目录

feign

SynchronousMethodHandler

第一部分

第二部分

第三部分

spring-cloud-openfeign

LoadBalancerFeignClient

ribbon

AbstractLoadBalancerAwareClient


在之前写的文章配置基础上

https://blog.csdn.net/zlpzlpzyd/article/details/136060312

因为从 spring boot 2.4.x 版本开始,匹配的 spring cloud 版本中去除了负载均衡组件 ribbon,可以看本人写的如下链接

https://blog.csdn.net/zlpzlpzyd/article/details/135696320

如果一定要使用 ribbon 相关功能,需要单独指定版本引入,spring 官方为了 ribbon 被移除的问题,自己开发了 spring-cloud-starter-loadbalancer。

feign设置参数如下

feign:client:config:default:connectTimeout: 1000readTimeout: 1000

服务提供者逻辑

@RestController
@RequestMapping(value = "user")
public class UserController implements Serializable {@GetMapping(value = "{id}")public User getUser(@PathVariable(value = "id") String id) {// int no = 1/0;try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}User user = new User();user.setId(id);user.setUserName("user_name_"+ id);user.setAge("20");return user;}}

可知,feign 调用此服务会出现超时问题。

异常堆栈调用如下

0 = {StackTraceElement@8542} "java.net.SocketInputStream.socketRead0(Native Method)"
1 = {StackTraceElement@8543} "java.net.SocketInputStream.socketRead(SocketInputStream.java:116)"
2 = {StackTraceElement@8544} "java.net.SocketInputStream.read(SocketInputStream.java:171)"
3 = {StackTraceElement@8545} "java.net.SocketInputStream.read(SocketInputStream.java:141)"
4 = {StackTraceElement@8546} "java.io.BufferedInputStream.fill(BufferedInputStream.java:246)"
5 = {StackTraceElement@8547} "java.io.BufferedInputStream.read1(BufferedInputStream.java:286)"
6 = {StackTraceElement@8548} "java.io.BufferedInputStream.read(BufferedInputStream.java:345)"
7 = {StackTraceElement@8549} "sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)"
8 = {StackTraceElement@8550} "sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)"
9 = {StackTraceElement@8551} "sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)"
10 = {StackTraceElement@8552} "sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)"
11 = {StackTraceElement@8553} "java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)"
12 = {StackTraceElement@8554} "feign.Client$Default.convertResponse(Client.java:113)"
13 = {StackTraceElement@8555} "feign.Client$Default.execute(Client.java:109)"
14 = {StackTraceElement@8556} "org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer.execute(FeignLoadBalancer.java:98)"
15 = {StackTraceElement@8557} "org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer.execute(FeignLoadBalancer.java:56)"
16 = {StackTraceElement@8558} "com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:103)"
17 = {StackTraceElement@8559} "com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303)"
18 = {StackTraceElement@8560} "com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287)"
19 = {StackTraceElement@8561} "rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231)"
20 = {StackTraceElement@8562} "rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228)"
21 = {StackTraceElement@8563} "rx.Observable.unsafeSubscribe(Observable.java:10327)"
22 = {StackTraceElement@8564} "rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)"
23 = {StackTraceElement@8565} "rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144)"
24 = {StackTraceElement@8566} "com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185)"
25 = {StackTraceElement@8567} "com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)"
26 = {StackTraceElement@8568} "rx.Observable.unsafeSubscribe(Observable.java:10327)"
27 = {StackTraceElement@8569} "rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94)"
28 = {StackTraceElement@8570} "rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42)"
29 = {StackTraceElement@8571} "rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)"
30 = {StackTraceElement@8572} "rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)"
31 = {StackTraceElement@8573} "rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)"
32 = {StackTraceElement@8574} "rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)"
33 = {StackTraceElement@8575} "rx.Observable.subscribe(Observable.java:10423)"
34 = {StackTraceElement@8576} "rx.Observable.subscribe(Observable.java:10390)"
35 = {StackTraceElement@8577} "rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:443)"
36 = {StackTraceElement@8578} "rx.observables.BlockingObservable.single(BlockingObservable.java:340)"
37 = {StackTraceElement@8579} "com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:110)"
38 = {StackTraceElement@8580} "org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:84)"
39 = {StackTraceElement@8581} "feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:125)"
40 = {StackTraceElement@8582} "feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:94)"
41 = {StackTraceElement@8583} "feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)"
42 = {StackTraceElement@8584} "com.sun.proxy.$Proxy71.getUser(Unknown Source)"
43 = {StackTraceElement@8585} "com.example.feign.consumer.controller.FeignController.test(FeignController.java:22)"
44 = {StackTraceElement@8586} "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)"
45 = {StackTraceElement@8587} "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"
46 = {StackTraceElement@8588} "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)"
47 = {StackTraceElement@8589} "java.lang.reflect.Method.invoke(Method.java:498)"
48 = {StackTraceElement@8590} "org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)"
49 = {StackTraceElement@8591} "org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)"
50 = {StackTraceElement@8592} "org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)"
51 = {StackTraceElement@8593} "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)"
52 = {StackTraceElement@8594} "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)"
53 = {StackTraceElement@8595} "org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)"
54 = {StackTraceElement@8596} "org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)"
55 = {StackTraceElement@8597} "org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)"
56 = {StackTraceElement@8598} "org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)"
57 = {StackTraceElement@8599} "org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)"
58 = {StackTraceElement@8600} "javax.servlet.http.HttpServlet.service(HttpServlet.java:626)"
59 = {StackTraceElement@8601} "org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)"
60 = {StackTraceElement@8602} "javax.servlet.http.HttpServlet.service(HttpServlet.java:733)"
61 = {StackTraceElement@8603} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)"
62 = {StackTraceElement@8604} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
63 = {StackTraceElement@8605} "org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)"
64 = {StackTraceElement@8606} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
65 = {StackTraceElement@8607} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
66 = {StackTraceElement@8608} "org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)"
67 = {StackTraceElement@8609} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
68 = {StackTraceElement@8610} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
69 = {StackTraceElement@8611} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
70 = {StackTraceElement@8612} "org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)"
71 = {StackTraceElement@8613} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
72 = {StackTraceElement@8614} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
73 = {StackTraceElement@8615} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
74 = {StackTraceElement@8616} "org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)"
75 = {StackTraceElement@8617} "org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)"
76 = {StackTraceElement@8618} "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)"
77 = {StackTraceElement@8619} "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)"
78 = {StackTraceElement@8620} "org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)"
79 = {StackTraceElement@8621} "org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)"
80 = {StackTraceElement@8622} "org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)"
81 = {StackTraceElement@8623} "org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)"
82 = {StackTraceElement@8624} "org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)"
83 = {StackTraceElement@8625} "org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)"
84 = {StackTraceElement@8626} "org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)"
85 = {StackTraceElement@8627} "org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)"
86 = {StackTraceElement@8628} "org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)"
87 = {StackTraceElement@8629} "org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)"
88 = {StackTraceElement@8630} "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)"
89 = {StackTraceElement@8631} "org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)"
90 = {StackTraceElement@8632} "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)"
91 = {StackTraceElement@8633} "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)"
92 = {StackTraceElement@8634} "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)"
93 = {StackTraceElement@8635} "java.lang.Thread.run(Thread.java:748)"

feign

SynchronousMethodHandler

首先在 SynchronousMethodHandler 通过反射调用 executeAndDecode() 发起请求。

如果执行正常,直接返回结果跳出循环,否则异常被捕获到,重试次数达到最大值后直接抛出异常跳出循环。

分为三个部分

第一部分

将每次请求时将请求计数重置

对于重试间隔是按照 period * 1.5^attempt 来计算。

period 默认是 100ms,attempt 的值与时间对应关系如下

attempt 值为 1,间隔为 100*1.5^1=150,即150ms

attempt 值为 2,间隔为 100*1.5^2=225,即225ms

attempt 值为 3,间隔为 100*1.5^3=337,即337ms

attempt 值为 4,间隔为 100*1.5^4=506,即506ms

attempt 值为 5,间隔为 100*1.5^5=759,即759ms

第二部分

正常执行返回跳出循环

第三部分

请求异常后重试处理,重试次数达到最大值后直接抛出异常跳出循环

将 IOException 包装到 FeignException

通过类的层次图,可以知道,SocketTimeoutException 是 IOException 的子类

spring-cloud-openfeign

LoadBalancerFeignClient

负责将 feign 原生调用转换为负载均衡调用

将 ClientException 转换为 IOException

ribbon

主要负责负载均衡处理,是客户端侧的实现。从服务注册的单个服务里找到匹配的实例进行调用。

AbstractLoadBalancerAwareClient

内层请求异常返回原始异常,外层异常使用 ribbon 的 ClientException 进行包装

最终通过 feign.Client.Default 来执行实际请求,如果引入了其他依赖(例如 feign-httpclient 或者 feign-hc5 或者 feign-okclient),会使用其他方式。

最终通过 native 函数调用 jvm 层次的 tcp 网络调用,出现异常返回 IOException。

可知,针对 feign 请求过程中出现异常无论如何返回的是 IOException,最终在 feign 的处理下包装为 FeignException。

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

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

相关文章

基于docker部署的Selenium Grid分布式自动化测试

01、什么是Selenium Grid Selenium Grid是Selenium套件的一部分,它专门用于并行运行多个测试用例在不同的浏览器、操作系统和机器上。 Selenium Grid有两个版本——老版本Grid 1和新版本Grid 2。我们只对新版本做介绍,因为Selenium团队已经逐渐遗弃老版…

【电路笔记】-PNP晶体管

PNP晶体管 文章目录 PNP晶体管1、概述2、PNP晶体管电路示例3、PNP晶体管识别1、概述 PNP 晶体管与我们在上一篇教程中看到的 NPN 晶体管器件完全相反。 在这种类型的 PNP 晶体管结构中,两个互连的二极管相对于之前的 NPN 晶体管是相反的。 这会产生正-负-正类型的配置,箭头…

Echarts 配置项 series 中的 data 是多维度

文章目录 需求分析 需求 如下图数据格式所示,现要求按照该格式进行绘制折线图 分析 在绘制折线图时,通常我们的 series 中的 data 数据是这样的格式 option {title: {text: Stacked Area Chart},tooltip: {trigger: axis,axisPointer: {type: cross…

车辆伤害VR安全教育培训复用性强

VR工地伤害虚拟体验是一种新兴的培训方式,它利用虚拟现实技术为参与者提供身临其境的体验。与传统的培训方式相比,VR工地伤害虚拟体验具有许多优势。 首先,VR工地伤害虚拟体验能够模拟真实的工作环境和事故场景,让参与者在安全的环…

论文阅读:Diffusion Model-Based Image Editing: A Survey

Diffusion Model-Based Image Editing: A Survey 论文链接 GitHub仓库 摘要 这篇文章是一篇基于扩散模型(Diffusion Model)的图片编辑(image editing)方法综述。作者从多个方面对当前的方法进行分类和分析,包括学习…

Python(38):Request的data需入参是json,用转换json.dumps(data)

Python接口自动化测试遇到问题:误传str类型给request 一:request接口请求数据用str传参报错,请求响应报错 排查原因:查看服务器报错是Json解析报错。 1.1、如果直接入参,进行request请求的数据: data请求值为&…

ElevenLabs用AI为Sora文生视频模型配音 ,景联文科技提供高质量真人音频数据集助力生成逼真音效

随着Open AI公司推出的Sora文生视频模型惊艳亮相互联网,AI语音克隆创企ElevenLabs又为Sora的演示视频生成了配音,所有的音效均由AI创造,与视频内容完美融合。 ElevenLabs的语音克隆技术能够从一分钟的音频样本中创建逼真的声音。为了实现这一…

2024蓝桥杯每日一题(双指针)

一、第一题:牛的学术圈 解题思路:双指针贪心 仔细思考可以知道,写一篇综述最多在原来的H指数的基础上1,所以基本方法可以是先求出原始的H指数,然后分类讨论怎么样提升H指数。 【Python程序代码】 n,l map(int,…

在win10中下载桌面版的docker并在docker中搭建运行基于linux的容器

在win10中下载桌面版的docker 1.背景 在很多时候需要linux系统部署项目,在win10中安装虚拟机并在虚拟机中安装linux系统比较繁琐,可以利用win10自带的hyper-v的虚拟机管理工具,打开该虚拟机管理工具,安装docker,并在…

[杂谈]QtCreator调试输出窗与chromium的调试输出窗

前言 在我接触最多的调试输出窗中,用得最多的就是QtCreator和chromium。发现一个有趣的现象记录一下。QtCreator在处理大量重复的输出的情况下,采用方式如下 QtCreator采用直接输出的方式,这样逻辑上很直观,但是当有大量的输出时…

<Linux> 初识线程

目录 前言: 一、什么是线程 (一)基本概念 (二)线程理解 (三)线程与进程的关系 (四)简单实用线程 (五)重谈虚拟地址空间 1. 页表的大小 2…

【UE5】游戏框架GamePlay

项目资源文末百度网盘自取 游戏框架 游戏 由 游戏模式(GameMode) 和 游戏状态(GameState) 所组成 加入游戏的 人类玩家 与 玩家控制器(PlayerController) 相关联 玩家控制器允许玩家在游戏中拥有 HUD,这样他们就能在关卡中拥有物理代表 玩家控制器还向玩家提供 …

深度学习-Softmax 回归 + 损失函数 + 图片分类数据集

Softmax 回归 损失函数 图片分类数据集 1 softmax2 损失函数1均方L1LossHuber Loss 3 图像分类数据集4 softmax回归的从零开始实现 1 softmax Softmax是一个常用于机器学习和深度学习中的激活函数。它通常用于多分类问题,将一个实数向量转换为概率分布。Softmax函…

docker安装和使用kafka

1. 启动zookeeper Kafka依赖zookeeper, 首先安装zookeeper -p:设置映射端口(默认2181) docker run --name zookeeper \--network app-tier \-e ALLOW_ANONYMOUS_LOGINyes \--restartalways \-d bitnami/zookeeper:latest2. 启动kafka docker…

LVS集群(Linux Virtual server)

集群概念lvs模型lvs调度算法lvs实现lvs高可用性,负载均衡 1 集群和分布式 系统性能扩展方式: Scale UP:垂直扩展,向上扩展,增强,性能更强的计算机运行同样的服务 升级单机的硬件设备Scale Out:水平扩展…

MySQL通过SQL语句进行递归查询

这里主要是针对于MySQL8.0以下版本,因为MySQL8.0版本出来了一个WITH RECURSIVE函数专门用来进行递归查询的 先看下表格数据,就是很普通的树结构数据,通过parentId关联上下级关系 下面我们先根据上级节点id递归获取所有的下级节点数据&#x…

回归测试重复测试

重复测试和回归测试在测试的过程中都会遇到过,出现的概率都是高频的,两者如何区分如下图: 回归测试 回归测试是什么? 回归测试(Regression Testing)是指在软件修改之后,对已有功能点重新执行测…

C/C++编程-理论学习-通信协议理论

通信协议理论 protobuf简述使用简介proto 文件为了nanopb 编译.proto文件修改生成器行为 streamsoutput streamsinput streams Data types(数据类型)Field callbacks(字段回调)Encoding callbacks(编码回调)Message descriptor(信息描述)三个关键字required、optional、repeate…

【C++】函数模板和类模板

目录 1.泛型编程 2.函数模板 2.1函数模板的定义格式 2.2函数模板的实例化 2.3函数模板参数的匹配原则 3.类模板 3.1类模板的定义格式 3.2类模板的实例化 3.3模板的分离编译 1.泛型编程 泛型编程:编写与类型无关的通用代码,是代码复用的一种手段…

分割模型TransNetR的pytorch代码学习笔记

这个模型在U-net的基础上融合了Transformer模块和残差网络的原理。 论文地址:https://arxiv.org/pdf/2303.07428.pdf 具体的网络结构如下: 网络的原理还是比较简单的, 编码分支用的是预训练的resnet模块,解码分支则重新设计了。…