Java 21/Spring Boot 3.1.6多API调用应用间歇性连接超时求助
间歇性连接超时问题排查求助
我们的应用基于Java 21和Spring Boot 3.1.6开发,作为Amadeus API的包装器,需调用35+个外部接口,目前出现间歇性连接超时情况。针对Amadeus API开展的负载测试均能正常返回结果,但其他使用Java 21、调用不同服务的同类应用也存在相同问题。
以下是相关代码及报错信息,恳请协助排查根本原因:
RestTemplate 配置代码
@Bean(name = "restTemplate") @Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) public RestTemplate restTemplate(RestTemplateBuilder builder) { return configureRestTemplate(builder); } private RestTemplate configureRestTemplate(RestTemplateBuilder builder) { RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory())); List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(); interceptors.add(new LoggingRequestInterceptor()); restTemplate.setInterceptors(interceptors); if (CollectionUtils.isEmpty(interceptors)) { interceptors = new ArrayList<>(); } HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); restTemplate.setRequestFactory(requestFactory); return restTemplate; }
API 调用代码
@Autowired private RestTemplate restTemplate;
private <T, U> U exchangeData(URI uri, T data, Class<U> clazz, HttpHeaders requestHeaders, HttpMethod method, boolean... errorCustomization) { HttpEntity<T> requestEntity = new HttpEntity<>(data, requestHeaders); ResponseEntity<U> response = null; try { response = restTemplate.exchange(uri, method, requestEntity, clazz); } catch (RestClientException e) { List<ErrorModel> errorDetails = new ArrayList<>(); errorDetails.add(new ErrorModel(e.getClass().getName(), e.getMessage())); LOG.error("Error while calling external service", e); throw applicationErrorConfig.createExternalException(ApiExternalErrorType.SERVER_INTERNAL_ERROR, errorDetails); } restErrorManagerUtil.handleExternalServerErrorForComposite(data, response.getBody(), errorCustomization); return response.getBody(); }
报错堆栈信息
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://xxxx**********************": Connect to https://xxxx********************** [domain/ip] failed: Operation timed out at org.springframework.web.client.RestTemplate.createResourceAccessException(RestTemplate.java:888) ... Caused by: org.apache.hc.client5.http.HttpHostConnectException: Connect to https://xxxx********************** [domain/ip] failed: Operation timed out ...
排查方向建议
补全连接池配置:当前
HttpComponentsClientHttpRequestFactory未配置任何连接池参数,默认连接数有限且无超时控制,高并发下易出现连接耗尽导致超时。建议添加连接池及超时配置:HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); // 设置连接超时、读取超时 requestFactory.setConnectTimeout(3000); requestFactory.setReadTimeout(5000); // 配置连接池 PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(200); // 最大总连接数 connectionManager.setDefaultMaxPerRoute(50); // 单路由最大连接数 requestFactory.setHttpClient(HttpClients.custom().setConnectionManager(connectionManager).build());排查Java 21网络特性兼容性:多个Java 21应用均出现该问题,需验证是否是Java 21网络默认参数变更导致。比如HTTP/2默认启用、TCP存活参数调整等,可强制使用HTTP/1.1测试:
RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(3000) .setConnectionRequestTimeout(3000) .setSocketTimeout(5000) .build(); CloseableHttpClient httpClient = HttpClients.custom() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .disableHttp2() // 禁用HTTP/2,强制使用HTTP/1.1 .build(); requestFactory.setHttpClient(httpClient);检查DNS解析问题:间歇性超时可能和DNS缓存过期、解析延迟有关,可尝试调整JVM DNS缓存参数(如
networkaddress.cache.ttl和networkaddress.cache.negative.ttl),或直接用IP地址调用接口验证是否缓解。调整RestTemplate作用域:当前RestTemplate为
request作用域,每次请求都会创建新实例,无法复用连接池,高并发下频繁创建销毁连接会引发超时。建议改为默认的singleton作用域,配合连接池复用连接资源。
内容的提问来源于stack exchange,提问作者jerald jacob
相关产品推荐
相关产品推荐

