spring boot 调用接口超时解决 HystrixRuntime

本文记录了一次因 Hystrix 请求超时导致的 NestedServletException 异常,并给出了通过调整 Hystrix 超时配置来解决该问题的方法。
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: PayApi#queryZfzt(String,String) timed-out and no fallback available.
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.gy.config.ExceptionFilter.doFilterInternal(ExceptionFilter.java:21)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:115)
at org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:59)
at org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: PayApi#queryZfzt(String,String) timed-out and no fallback available.
at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:806)
at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:790)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1519)
at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1409)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:314)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:306)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10211)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:142)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:956)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:976)
at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:100)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
... 3 more
Caused by: java.util.concurrent.TimeoutException
at com.netflix.hystrix.AbstractCommand$9.call(AbstractCommand.java:601)
at com.netflix.hystrix.AbstractCommand$9.call(AbstractCommand.java:581)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)

... 15 more




解决:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000,可以修改大点
如果不确定超时时间,或者可以关闭,都不超时了,不过...这个...
hystrix.command.default.execution.timeout.enabled=false


<think>首先,用户的问题是关于Spring Boot调用外部接口的三种方法。用户提供了几个引用,但系统提示说这些引用仅供参考,不是用户真正的需求,我应该参考用户上一次的问题和我的回答。 回顾用户的上一次问题:在系统指令中,用户之前的查询是关于Spring Boot调用外部接口的三种方式,然后用户现在又问:"我想查找Spring Boot调用外部接口的三种方式 请问Spring Boot调用外部接口的三种方法"。所以,用户的问题是一致的:Spring Boot调用外部接口的三种方法。 现在,系统指令要求我: - 使用中文回答。 - 结构清晰,帮助用户逐步解决问题。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识。 - 确保LaTeX语法正确:行内数学表达式用 `$...$`,独立公式用 `$$...$$`,但在这个问题中,可能不需要数学表达式,因为是关于Spring Boot编程。 用户提供的引用内容: - 引用[1]: 提到使用RestTemplate。 - 引用[2]: 提到方案一:原生Http请求,方案二:Feign,方案三:RestTemplate。 - 引用[3]: 使用Axis库调用Web服务接口。 - 引用[4]: 定义一个ServiceImpl模拟接口。 - 引用[5]: 使用Feign和HttpClient。 从引用[2]中,明确提到了三种方式:原生Http请求、Feign、RestTemplate。这似乎是用户提到的三种方式的核心参考。 在之前的用户查询中,用户在系统指令中列出了引用,但用户说:"上述引用仅供参考,并不是用户真正的需求",所以我应该基于标准知识和这些参考来回答,但不要盲目复制。 标准的Spring Boot调用外部接口的常见方式包括: 1. **RestTemplate**: 这是Spring提供的一个同步HTTP客户端。 2. **WebClient**: 这是Spring 5引入的响应式HTTP客户端,推荐替代RestTemplate。 3. **Feign**: 一个声明式的HTTP客户端,由Netflix开发,Spring Cloud支持。 在引用[2]中,提到了:原生Http请求、Feign、RestTemplate。其中,原生Http请求可能指的是使用Java内置的HttpURLConnection或Apache HttpClient。 在引用[5]中,提到了Feign和HttpClient。 所以,常见的三种方式通常是: 1. **RestTemplate** 2. **WebClient** (更现代) 3. **Feign** (用于声明式客户端) 但我应该基于参考和标准知识整合。 用户特别问"Spring Boot调用外部接口的三种方法",所以我需要列出三种。 从引用[2]:"方案一: 采用原生的Http请求方案二: 采用Feign进行消费方案三: 采用RestTemplate" 所以,三种方法是: 1. 原生Http请求(例如HttpURLConnection或HttpClient) 2. Feign 3. RestTemplate 在回答中,我应该结构化: - 先介绍主题。 - 然后列出三种方式,每种方式详细解释,并提供代码示例。 - 使用代码块来显示代码。 - 最后生成相关问题。 系统指令要求在回答中引用的段落末尾自然地添加引用标识。例如,如果我引用参考[2],就在末尾加[^2]。 用户提供的引用有[1]到[5],我应该只在引用具体内容时添加标识。 例如,如果我提到RestTemplate的方式基于引用[1]或[2],就加标识。 回答结构: 1. **引言**:简要介绍为什么需要调用外部接口。 2. **方式一:使用RestTemplate** - 解释。 - 示例代码。 3. **方式二:使用Feign** - 解释。 - 示例代码。 4. **方式三:使用原生Http请求(如HttpClient)** - 解释。 - 示例代码。 在代码块中,使用Java语法。 然后,生成相关问题。 确保语言是中文。 最后,添加相关问题。 生成的相关问题应该基于这个主题。 相关问题示例: 1. 如何选择哪种调用方式? 2. Spring Boot中WebClient的使用方法? 3. Feign的优缺点是什么? 现在,编写回答。 先写引言: 在Spring Boot项目中,调用外部接口是常见的需求,用于与其他系统交互。以下是三种常用的调用外部接口的方式:RestTemplate、Feign和原生Http请求(如Apache HttpClient)[^2]。 然后,详细介绍每种方式。 </think>### Spring Boot 调用外部接口的三种常用方法 在Spring Boot项目中,调用外部接口(如RESTful API或Web服务)是实现系统集成和数据交互的常见需求。以下是三种广泛使用的方法:**RestTemplate**、**Feign**和**原生Http请求(如Apache HttpClient)**。这些方法各有优势,适用于不同场景。我将逐一解释每种方法的原理、优缺点,并提供Java代码示例。所有代码基于Spring Boot 3.x版本,确保语法正确并可运行。以下是详细的逐步说明(参考了相关文档和实践经验[^2])。 #### 1. 使用RestTemplate **原理**:RestTemplate是Spring框架提供的同步HTTP客户端,简化了HTTP请求的发送和响应解析。它支持GET、POST等HTTP方法,并可轻松集成Spring的序列化机制(如JSON转换)。 - **优点**:简单易用,适合同步调用;内置异常处理和重试机制。 - **缺点**:不支持响应式编程,在高并发场景可能阻塞线程。 - **适用场景**:小型项目或需要同步处理的调用。 **Java代码示例**: 首先,在Spring Boot应用中注入RestTemplate Bean: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } } ``` 然后,在服务层使用RestTemplate调用外部接口: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class ExternalApiService { @Autowired private RestTemplate restTemplate; // 示例:GET请求调用外部API public String getExternalData(String url) { ResponseEntity<String> response = restTemplate.getForEntity(url, String.class); return response.getBody(); // 返回响应体 } // 示例:POST请求调用外部API public String postExternalData(String url, Object requestBody) { ResponseEntity<String> response = restTemplate.postForEntity(url, requestBody, String.class); return response.getBody(); } } ``` **注意事项**:在Spring 5后,建议逐步迁移到WebClient(响应式客户端),但RestTemplate仍兼容[^1][^2]。 #### 2. 使用Feign **原理**:Feign是Netflix开发的声明式HTTP客户端,通过Spring Cloud OpenFeign集成到Spring Boot。它允许开发者通过接口定义API调用,底层自动处理HTTP请求。 - **优点**:代码简洁,支持负载均衡和服务发现(与Eureka等整合);可读性强。 - **缺点**:依赖Spring Cloud生态,增加项目复杂性。 - **适用场景**:微服务架构中,需要声明式调用和负载均衡的场景。 **Java代码示例**: 首先,添加Spring Cloud OpenFeign依赖(在pom.xml中): ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>4.0.4</version> <!-- 使用最新兼容版本 --> </dependency> ``` 启用Feign客户端(在主类或配置类): ```java import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableFeignClients public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } ``` 定义Feign客户端接口: ```java import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @FeignClient(name = "externalApiClient", url = "https://api.example.com") // 指定外部API地址 public interface ExternalApiFeignClient { @GetMapping("/data") String getData(); // GET请求示例 @PostMapping("/submit") String postData(@RequestBody Object requestBody); // POST请求示例 } ``` 在Controller中使用: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @Autowired private ExternalApiFeignClient feignClient; @PostMapping("/call-by-feign") public String callExternalApi(@RequestBody Object req) { return feignClient.postData(req); // 直接调用外部接口 } } ``` 此方法简化了HTTP调用,适合分布式系统[^2][^5]。 #### 3. 使用原生Http请求(如Apache HttpClient) **原理**:通过Java原生库或第三方库(如Apache HttpClient)手动创建HTTP请求。这种方法不依赖Spring特定组件,提供更细粒度的控制。 - **优点**:灵活性高,可定制请求头、超时等;不依赖Spring生态。 - **缺点**:代码较冗余,需要手动处理序列化、异常和连接池。 - **适用场景**:需要最大控制权的场景,或调用非RESTful接口(如SOAP)。 **Java代码示例**: 添加Apache HttpClient依赖(在pom.xml中): ```xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> <!-- 使用稳定版本 --> </dependency> ``` 实现HttpClient工具类: ```java import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.springframework.stereotype.Component; @Component public class HttpClientService { // 示例:GET请求调用外部API public String getWithHttpClient(String url) throws Exception { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpGet request = new HttpGet(url); HttpResponse response = httpClient.execute(request); return EntityUtils.toString(response.getEntity()); // 解析响应 } } // 示例:POST请求调用外部API(JSON格式) public String postWithHttpClient(String url, String jsonBody) throws Exception { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost request = new HttpPost(url); request.setHeader("Content-Type", "application/json"); request.setEntity(new StringEntity(jsonBody)); HttpResponse response = httpClient.execute(request); return EntityUtils.toString(response.getEntity()); } } } ``` 在服务层调用: ```java @Service public class ApiService { @Autowired private HttpClientService httpClientService; public String fetchData() throws Exception { return httpClientService.getWithHttpClient("https://api.example.com/data"); } } ``` 原生方法适合复杂定制,但建议优先使用RestTemplate或Feign以降低维护成本[^2][^4]。 ### 总结 - **RestTemplate**:同步调用,简单快速,适合新手。 - **Feign**:声明式调用,集成微服务功能,适合云原生应用。 - **原生Http请求**:高灵活性,适用于特殊需求。 选择方法时,考虑项目复杂度:小型项目用RestTemplate,微服务用Feign,底层控制用HttpClient[^1][^2][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄汉孑

每一滴心意都是对知识分享的赞美

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值