From c6053055a40c4ffdbc53f7b99cccc63917009e9c Mon Sep 17 00:00:00 2001 From: curry772 Date: Fri, 11 Sep 2026 11:13:29 +0900 Subject: [PATCH] =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89=20?= =?UTF-8?q?=EC=8B=9C=20=EC=BB=A4=EB=84=A5=EC=85=98=20=ED=92=80=20=EA=B3=A0?= =?UTF-8?q?=EA=B0=88=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 풀 대기 시간 미지정 시 기본 3분을 기다려, 스케줄러 태스크 타임아웃(30초)에 먼저 인터럽트되고 커넥션이 반납되지 않아 캐시한 풀이 마르는 문제 - setConnectionRequestTimeout 지정으로 풀 대기도 CONNECTION_TIMEOUT 을 따르도록 함 - evictExpiredConnections / evictIdleConnections 추가로 캐시한 풀의 죽은 커넥션 정리 --- .../impl/HttpClientAccessTokenServiceWithConfig.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithConfig.java b/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithConfig.java index 2183554..ed46fe1 100644 --- a/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithConfig.java +++ b/src/main/java/com/eactive/eai/authoutbound/client/impl/HttpClientAccessTokenServiceWithConfig.java @@ -41,6 +41,7 @@ import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicNameValuePair; import org.apache.hc.core5.net.URIBuilder; import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; import org.springframework.security.web.util.UrlUtils; @@ -155,6 +156,9 @@ public class HttpClientAccessTokenServiceWithConfig implements HttpClientAccessT private static final long DEFAULT_EXPIRES_IN = 3600L; + /** 캐시한 HttpClient 의 유휴 커넥션 정리 주기(초) */ + private static final int IDLE_CONNECTION_EVICT_SECONDS = 30; + /** * mTLS 여부/clientId 조합별로 CloseableHttpClient(및 내부 PoolingHttpClientConnectionManager)를 * 1회만 생성해 재사용한다. 이 서비스 인스턴스는 HttpClientAccessTokenServiceFactoryByDB 에 @@ -381,8 +385,11 @@ public class HttpClientAccessTokenServiceWithConfig implements HttpClientAccessT requestConfigBuilder.setProxy(proxy); } + // 커넥션 풀 대기 시간을 지정하지 않으면 기본 3분을 기다린다. 스케줄러의 태스크 타임아웃(30초)이 + // 먼저 걸려 요청이 인터럽트되고, 그 과정에서 커넥션이 반납되지 않아 풀이 마르는 악순환이 생긴다. RequestConfig requestConfig = requestConfigBuilder .setConnectTimeout(Timeout.ofMilliseconds(connectionTimeout)) + .setConnectionRequestTimeout(Timeout.ofMilliseconds(connectionTimeout)) .setResponseTimeout(Timeout.ofMilliseconds(timeout)).build(); request.setConfig(requestConfig); @@ -641,7 +648,10 @@ public class HttpClientAccessTokenServiceWithConfig implements HttpClientAccessT adapterGroupName, useMtls, clientId, contentCompression, defaultUserAgent); } - HttpClientBuilder builder = HttpClients.custom().setConnectionManager(connectionManager); + // HttpClient 를 캐시해 재사용하므로 죽은 커넥션이 풀에 남지 않도록 정리 설정을 건다. + HttpClientBuilder builder = HttpClients.custom().setConnectionManager(connectionManager) + .evictExpiredConnections() + .evictIdleConnections(TimeValue.ofSeconds(IDLE_CONNECTION_EVICT_SECONDS)); if (!contentCompression) { builder.disableContentCompression(); }