HttpClient NoHttpResponseException 개요
Apache HttpClient 사용 시 서버 응답이 없는 경우 NoHttpResponseException이 발생합니다. 이는 서버의 응답 지연 또는 연결 문제로 인해 클라이언트가 응답을 수신하지 못할 때 발생하는 오류입니다.
주요 발생 시나리오
- 서버 장애 또는 과부하 상태
- 네트워크 연결 불안정
- 프록시 서버 재시작(예: nginx reload)
오류 발생 사례
org.apache.http.NoHttpResponseException: example.com:80 failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
...
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
근본 원인 분석
Nginx reload 작업 수행 시 발생하는 경우가 빈번합니다. 재시작 과정에서 서버가 FIN 패킷을 전송하지만 클라이언트가 이를 인지하지 못해 유효하지 않은 연결을 재사용하려 할 때, 서버가 RST 패킷으로 응답하면 예외가 발생합니다.
효과적인 해결 전략
- Nginx reload 작업 최소화
- 연결 유지 시간 설정 최적화
- Tomcat: keepalive_timeout ≈ 75초
- Nginx: keepalive_timeout 75 74
- 클라이언트 연결 검증 주기 조정
HttpClient 연결 설정 예제
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
public class HttpConnectionManager {
public CloseableHttpClient createCustomClient(
int maxConnections,
int idleTimeoutSec,
int connectionTTLSec,
int validationIntervalMs) {
PoolingHttpClientConnectionManager connManager =
new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(maxConnections);
connManager.setDefaultMaxPerRoute(maxConnections);
connManager.setValidateAfterInactivity(validationIntervalMs);
return HttpClientBuilder.create()
.setConnectionManager(connManager)
.evictIdleConnections(idleTimeoutSec, TimeUnit.SECONDS)
.setConnectionTimeToLive(connectionTTLSec, TimeUnit.SECONDS)
.build();
}
}
주요 설정 매개변수
- setValidateAfterInactivity: 연결 재사용 전 유효성 검사 주기(ms)
- evictIdleConnections: 유휴 연결 제거 시간 임계값
- setConnectionTimeToLive: 연결 최대 수명