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: 1000
        readTimeout: 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.mfbz.cn/a/444324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Excel F4键的作用

目录 一. 单元格相对/绝对引用转换二. 重复上一步操作 一. 单元格相对/绝对引用转换 ⏹ 使用F4键 如下图所示,B1单元格引用了A1单元格的内容。此时是使用相对引用,可以按下键盘上的F4键进行相对引用和绝对引用的转换。 二. 重复上一步操作 ⏹添加或删除…

【Python】装饰器函数

专栏文章索引:Python 原文章:装饰器函数基础_装饰函数-CSDN博客 目录 1. 学习装饰器的基础 2.最简单的装饰器 3.闭包函数装饰器 4.装饰器将传入的函数中的值大写 5. 装饰器的好处 6. 多个装饰器的执行顺序 7. 装饰器传递参数 8. 结语 1. 学习装饰…

c++中string的模拟实现(超详细!!!)

1.string的成员变量、(拷贝)构造、析构函数 1.1.成员变量 private:char* _str;size_t _size; //string中有效字符个数size_t _capacity; //string中能存储有效字符个数的大小 1.2(拷贝)构造函数 //构造函数string(const char* …

Chain of Verification(验证链、CoVe)—理解与实现

原文地址:Chain of Verification (CoVe) — Understanding & Implementation 2023 年 10 月 9 日 GitHub 存储库 介绍 在处理大型语言模型(LLM)时,一个重大挑战,特别是在事实问答中,是幻觉问题。当答案…

React-路由导航

1.声明式路由导航 1.1概念 说明&#xff1a;声明式导航是指通过在模版中通过<Link/>组件描述出要跳转到哪里去&#xff0c;比如后台管理系统的左侧菜单通常使用这种方式进行。 import {Link} from "react-router-dom" const Login()>{return (<div>…

资源哟正版无授权模版源码(含搭建教程)

资源哟 v1.3 – 新增两种首页布局 – 新增幻灯片插件 – 优化深色模式颜色效果 – 优化导航页面左侧栏目跳转效果 – 优化后台辅助插件当前页面打开 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88898100 更多资源下载&#xff1a;关注我。

Linux多线程之线程控制

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 一、pthread_crate 二、pthread_join 三、p…

RAG、数据隐私、攻击方法和安全提示

原文地址&#xff1a;RAG, Data Privacy, Attack Methods & Safe-Prompts 最近的一项研究探讨了 RAG 安全漏洞以及通过检索数据集访问私有数据的方式。还讨论了防御和安全提示工程示例。 介绍 RAG 在构建生成式 AI 应用程序中非常受欢迎。RAG 在生成式 AI 应用中采用的原因…

Elasticsearch架构原理

一. Elasticsearch架构原理 1、Elasticsearch的节点类型 在Elasticsearch主要分成两类节点&#xff0c;一类是Master&#xff0c;一类是DataNode。 1.1 Master节点 在Elasticsearch启动时&#xff0c;会选举出来一个Master节点。当某个节点启动后&#xff0c;然后使用Zen D…

指针数组和数组指针(详细解释)

指针数组 指针数组的作用 指针数组和数组指针是C语言中常用的概念&#xff0c;它们分别有不同的作用和用法。 指针数组&#xff1a; 指针数组是一个数组&#xff0c;其中的每个元素都是指针类型。它可以用来存储多个指针&#xff0c;每个指针可以指向不同的数据类型或者相同…

Pytorch学习 day08(最大池化层、非线性激活层、正则化层、循环层、Transformer层、线性层、Dropout层)

最大池化层 最大池化&#xff0c;也叫上采样&#xff0c;是池化核在输入图像上不断移动&#xff0c;并取对应区域中的最大值&#xff0c;目的是&#xff1a;在保留输入特征的同时&#xff0c;减小输入数据量&#xff0c;加快训练。参数设置如下&#xff1a; kernel_size&#…

类与对象-对象特性

师从黑马程序员 对象的初始化和清理 构造函数和析构函数 用于完成对象的初始化和清理工作 如果我们不提供构造和析构&#xff0c;编译器会提供编译器提供的构造函数和析构函数是空实现 构造函数&#xff1a;主要用于创建对象时为对象的成员属性赋值&#xff0c;构造函数由编…

了解华为(PVID VLAN)与思科的(Native VLAN)本征VLAN的区别并学习思科网络中二层交换机的三层结构局域网VLAN配置

一、什么是二层交换机&#xff1f; 二层交换机&#xff08;Layer 2 Switch&#xff09;是一种网络设备&#xff0c;主要工作在OSI模型的数据链路层&#xff08;第二层&#xff09;&#xff0c;用于在局域网内部进行数据包的交换和转发。二层交换机通过学习MAC地址表&#xff0…

毅速3D打印随形透气钢:模具困气排气革新之选

在注塑生产过程中&#xff0c;模具内的气体若无法有效排出&#xff0c;往往会引发困气现象&#xff0c;导致产品表面出现气泡、烧焦等瑕疵。这些瑕疵不仅影响产品的美观度&#xff0c;更可能对其性能造成严重影响&#xff0c;甚至导致产品报废&#xff0c;从而增加生产成本。 传…

政安晨:【深度学习处理实践】(四)—— 实施一个温度预测示例

在开始使用像黑盒子一样的深度学习模型解决温度预测问题之前&#xff0c;我们先尝试一种基于常识的简单方法。 它可以作为一种合理性检查&#xff0c;还可以建立一个基准&#xff0c;更高级的机器学习模型需要超越这个基准才能证明其有效性。对于一个尚没有已知解决方案的新问…

Linux之生产消费者模型

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 我们在条件满足的时候&#xff0c;唤醒指定的线程&a…

超越Chain-of-Thought LLM 推理

原文地址&#xff1a;Beyond Chain-of-Thought LLM Reasoning 2024 年 2 月 13 日 介绍 最近的一项研究解决了需要增强大型语言模型 (LLM) 的推理能力&#xff0c;超越直接推理 (Direct Reasoning&#xff0c;DR) 框架&#xff0c;例如思想链和自我一致性&#xff0c;这些框架可…

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

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

HTML入门:属性

你好&#xff0c;我是云桃桃。今天来聊一聊 HTML 属性写法和特点。 HTML 属性是用于向 HTML 标签&#xff08;也叫 HTML 元素&#xff09;提供附加信息或配置的特性。 如果说&#xff0c;把HTML 标签比作一个房子&#xff0c;HTML 标签定义了房子的结构和用途&#xff0c;比如…

基于SpringBoot的闲置房屋搜索平台设计与实现

目 录 摘 要 I Abstract II 引 言 1 1相关技术 3 1.1 jQuery技术简介 3 1.2 SpringBoot框架简介 3 1.3 Bootstrap框架简介 4 1.4 ECharts框架简介 4 1.5 百度地图API简介 4 1.6 Ajax技术简介 5 1.7 MySQL数据库简介 5 1.8本章小结 6 2系统分析 7 2.1功能需求 7 2.2非功能需求 …
最新文章