Spring boot, Exiting but response remains open for further handling
Servlet Async 비동기 통신의 무한 pending이 걸렸을 때는 타임아웃을 걸어주자
Jul 25, 2024
문제 상황 및 원인
회사 백오피스 서버에서 다른 서버로 요청을 보내 응답 값을 받아오는 여러 기능이 있다. 그런데 특정 기능에서 요청에 대한 응답이 없을 때, 다음과 같은 로그와 함께 백오피스 서버가 다운되는 현상이 발생했다:
Exiting but response remains open for further handling
기본적으로 프로젝트는 Servlet Async 방식을 사용하고 있으며, Spring MVC 3.2부터 Servlet 3.0 기반의 비동기 요청 처리를 사용하고 있다. 기존 Controller 메서드를
Callable
로 변경하여 비동기 처리를 구현하고 있다.사용 예시:
public Callable<ResponseDto> postMethod( @Valid @RequestBody Dto dto ){ return () -> commonService.postMethod(dto); }
문제는 백오피스 서버가 다른 서버에 보낸 요청에 대한 응답이 돌아오지 않을 때 발생하며, 이로 인해 서버가 다음과 같은 메시지를 로그로 남기고 다른 요청도 무한 대기 상태에 빠진다:
Exiting but response remains open for further handling
이 상황이 발생하면 백오피스 서버의 다른 기능도 먹통이 되어 큰 문제가된다.
해결책
문제 해결은 비교적 간단하다. 비동기 통신의 타임아웃을 설정하여, 특정 시간이 지난 비동기 요청은 타임아웃 처리되고
AsyncRequestTimeoutException
을 발생시키도록 합니다. 이를 통해 비동기 요청에 대한 에러 핸들링을 할 수 있다.Spring의
WebMvcConfigurer
에서 AsyncSupportConfigurer
를 통해 타임아웃을 설정할 수 있다:@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) { configurer.setDefaultTimeout(10000); } }
위와 같이 설정하면, 비동기 요청이 10초를 초과할 경우 타임아웃이 발생하고
AsyncRequestTimeoutException
이 발생한다. 이를 @ExceptionHandler
를 통해 처리할 수 있다.근본 원인
근본적인 문제는 방화벽 설정으로 인해 다른 서버에서 백오피스 서버로의 요청이 막혀있는 상태였다. 하지만 서버가 다운되는 현상을 방지하기 위해 비동기 통신에 대한 타임아웃과 에러 핸들링을 통해 문제를 해결했다.
요약
- 문제 상황: 비동기 요청의 응답 지연 시 서버가 다운되고 다른 요청도 무한 대기 상태에 빠짐.
- 원인: 다른 서버와의 통신 문제로 인해 응답이 지연됨.
- 해결책: 비동기 요청에 타임아웃 설정을 통해
AsyncRequestTimeoutException
을 발생시키고 이를 처리하여 서버가 다운되는 현상을 방지.
- 근본 원인: 방화벽 설정 문제로 인해 다른 서버에서 백오피스 서버로의 요청이 막힘.
고민해볼 문제
- 타임아웃 설정 강화: 비동기 요청의 타임아웃 설정을 환경 변수나 설정 파일로 외부화하여 쉽게 조정
- 모니터링 및 알림: 비동기 요청의 타임아웃이나 실패 시 모니터링 및 알림 시스템을 구축하여 신속하게 문제를 파악하고 대응.
- 방화벽 설정 확인: 다른 서버와의 통신 문제가 발생하지 않도록 방화벽 설정을 정기적으로 테스트
Share article