当前位置:   article > 正文

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

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设置参数如下

  1. feign:
  2. client:
  3. config:
  4. default:
  5. connectTimeout: 1000
  6. readTimeout: 1000

服务提供者逻辑

  1. @RestController
  2. @RequestMapping(value = "user")
  3. public class UserController implements Serializable {
  4. @GetMapping(value = "{id}")
  5. public User getUser(@PathVariable(value = "id") String id) {
  6. // int no = 1/0;
  7. try {
  8. TimeUnit.SECONDS.sleep(5);
  9. } catch (InterruptedException e) {
  10. throw new RuntimeException(e);
  11. }
  12. User user = new User();
  13. user.setId(id);
  14. user.setUserName("user_name_"+ id);
  15. user.setAge("20");
  16. return user;
  17. }
  18. }

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

异常堆栈调用如下

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/232329
推荐阅读
相关标签
  

闽ICP备14008679号