토큰 발급 시 커넥션 풀 고갈 방지

- 풀 대기 시간 미지정 시 기본 3분을 기다려, 스케줄러 태스크 타임아웃(30초)에 먼저 인터럽트되고
  커넥션이 반납되지 않아 캐시한 풀이 마르는 문제
- setConnectionRequestTimeout 지정으로 풀 대기도 CONNECTION_TIMEOUT 을 따르도록 함
- evictExpiredConnections / evictIdleConnections 추가로 캐시한 풀의 죽은 커넥션 정리
This commit is contained in:
curry772
2026-09-11 11:13:29 +09:00
parent 0f9d38918a
commit c6053055a4
@@ -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();
}