HOWTO · Java
Java.Net.SocketTimeoutException: Tomcat에서 읽기 시간 초과
오늘의 자습서에서는 java.net.SocketTimeoutException: Java의 Tomcat에서 읽기 시간 초과에 대한 잠재적인 이유와 솔루션에 대해 설명합니다.
이 페이지의 내용
Java에서 java.net.SocketTimeoutException: Read timed out이 발생했다면, 소켓에서 데이터를 읽는 동안 해당 읽기에 설정된 대기 시간이 끝날 때까지 데이터를 받지 못했다는 뜻입니다. 이 메시지만으로는 지연의 원인이 원격 서비스인지, 네트워크인지, 애플리케이션 작업인지, 호출자가 설정한 시간 제한인지 알 수 없습니다. 먼저 어느 읽기 작업에서 문제가 발생했는지 추적한 다음, 그 작업을 제어하는 시간 제한만 조정하세요. (Read timed out)
java.net.SocketTimeoutException: Read timed out의 의미
읽기 시간 제한은 Java 소켓 읽기 작업이 데이터를 기다리는 시간을 제한합니다. 통신의 다른 단계를 제어하는 연결 시간 제한과는 다릅니다. 스택 추적을 보면 해당 읽기가 HTTP 클라이언트, 데이터베이스 드라이버 또는 애플리케이션 코드 중 어디에서 시작되었는지 확인할 수 있습니다. 호출 지점과 주변 로그를 살펴 어떤 작업인지 파악하세요.
이 메시지가 Tomcat이 클라이언트에 응답하지 못했다는 증거는 아닙니다. 오류를 기록한 Java 프로세스가 업스트림 서비스에서 데이터를 읽고 있었을 수도 있고, 시간 초과된 읽기가 시작되기 전에 상대편이 일부 데이터를 보냈을 수도 있습니다. 확인할 수 있다면 스택 추적을 요청 ID, 타임스탬프, 양쪽의 로그와 대조하세요.
어떤 시간 제한이 만료되는지 확인하기
예외의 스택 추적에서 읽기를 시작한 첫 애플리케이션 또는 라이브러리 프레임을 찾으세요. HTTP 응답, 데이터베이스 결과 또는 다른 소켓 중 무엇을 읽는지 확인한 다음 해당 클라이언트의 설정과 문서에서 읽기 또는 응답 시간 제한을 살펴보세요. 시간 초과된 읽기를 실제로 그 클라이언트가 제어하는 경우에만 브라우저나 프런트엔드의 시간 제한을 확인하면 됩니다.
호출 경로에 Tomcat이 보인다면 어느 프로세스가 오류를 기록했으며 어떤 연결에서 데이터를 읽고 있었는지 파악하세요. 외부로 요청을 보내는 Java 클라이언트의 시간 제한은 Tomcat Connector 설정과 별개입니다. 예외 메시지만으로 어느 설정이 원인인지 단정하지 마세요.
관련 Tomcat 시간 제한 설정하기
connectionTimeout은 Tomcat Connector 설정이지만, 구체적인 동작과 기본값은 사용 중인 Tomcat 버전과 Connector에 따라 다릅니다. 이 설정은 Java 클라이언트의 소켓 읽기 시간 제한과 서로 바꿔 쓸 수 없습니다. Tomcat 10.1 Connector 설정 문서를 참고하고, 배포된 Tomcat 버전에 해당하는 문서에서 스택 추적으로 확인한 작업에 그 설정이 적용되는지 검토하세요. 제공된 정보에는 Tomcat 버전이 없으므로 Connector XML 변경을 안전하게 권할 수 없습니다.
소켓을 소유한 Java 클라이언트에서는 Socket.setSoTimeout으로 해당 소켓의 읽기 시간 제한을 설정합니다. 다음 프로그램은 설정된 값을 다시 읽어 출력합니다. 변경되지 않은 예제와 출력 블록은 설정값을 보여 주며, 코드 블록 안의 표시 문자열은 바이트 단위 원문 보존을 위해 영어 그대로입니다.
import java.io.IOException;
import java.net.Socket;
class ReadTimeoutSetup {
public static void main(String[] args) throws IOException {
try (Socket socket = new Socket()) {
socket.setSoTimeout(5000);
System.out.println("Read timeout: " + socket.getSoTimeout() + " ms");
}
}
}
Read timeout: 5000 ms
이 예제는 서버에 연결하지 않으며 Tomcat 설정도 변경하지 않습니다. 클라이언트 측 설정은 시간 초과가 발생한 읽기를 소유한 구성 요소에서만 적용하고, 선택한 값이 해당 클라이언트 API와 운영 요구사항에 맞는지 확인하세요.
네트워크, 서버, 애플리케이션 지연 진단하기
호출자, Tomcat, 업스트림 서비스의 타임스탬프와 요청 ID를 확인하세요. 응답 데이터가 도착하지 않은 구간을 찾아 네트워크 오류, 서버 로그, 애플리케이션 추적 정보와 비교합니다. 데이터 지연은 네트워크 지연, 느린 애플리케이션 작업이나 데이터베이스 쿼리, 리소스 경합, 동시 부하 때문에 발생할 수 있습니다. 이런 항목은 조사할 단서이지, 예외 메시지만으로 확정할 수 있는 원인은 아닙니다.
같은 시간대의 CPU, 메모리, 스레드, 연결 풀, 데이터베이스 지표를 살펴보세요. 해당 요청이 애플리케이션에 도달했는지, 다운스트림 호출이나 쿼리가 평소보다 오래 걸렸는지 확인합니다. 서비스 앞에 프록시나 로드 밸런서가 있다면 해당 구성 요소의 시간 제한과 로그를 클라이언트 및 서버의 기록과 대조하세요. 관련 설정은 한 번에 하나씩 변경하고, 지연의 원인을 계속 조사하면서 해당 읽기 작업이 완료되는지 관찰하세요.
장시간 요청을 안전하게 처리하기
작업에 실제로 동기식 요청의 대기 시간보다 더 오래 걸린다면 비동기 처리를 고려하세요. 요청을 접수했다는 응답과 작업 ID를 반환하고, 작업은 별도로 수행한 뒤 클라이언트가 완료 여부를 확인하도록 구성할 수 있습니다. 이렇게 하면 작업이 끝날 때까지 요청을 열어 둘 필요가 없지만, 애플리케이션에서 이를 지원하고 실패나 진행 상황을 명확히 알릴 방법이 있어야 합니다.
더 긴 대기가 적절한 경우에도 확인된 읽기 작업을 제어하는 시간 제한만 늘리고, 관련 클라이언트·프록시·서버의 한도는 서로 맞추세요. 대기 시간이 지나치게 길면 스레드, 소켓 또는 다른 리소스를 점유하고 서비스 속도 저하를 가릴 수 있습니다. 관찰된 요청 처리 시간과 시스템 용량을 기준으로 값을 정한 뒤, 완료율과 리소스 사용량을 함께 모니터링하세요.