Spring boot, Exiting but response remains open for further handling

Servlet Async 비동기 통신의 무한 pending이 걸렸을 때는 타임아웃을 걸어주자
김주혁's avatar
Jul 25, 2024
Spring boot, Exiting but response remains open for further handling
 

문제 상황 및 원인

회사 백오피스 서버에서 다른 서버로 요청을 보내 응답 값을 받아오는 여러 기능이 있다. 그런데 특정 기능에서 요청에 대한 응답이 없을 때, 다음과 같은 로그와 함께 백오피스 서버가 다운되는 현상이 발생했다:
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를 통해 처리할 수 있다.

근본 원인

근본적인 문제는 방화벽 설정으로 인해 다른 서버에서 백오피스 서버로의 요청이 막혀있는 상태였다. 하지만 서버가 다운되는 현상을 방지하기 위해 비동기 통신에 대한 타임아웃과 에러 핸들링을 통해 문제를 해결했다.

요약

  1. 문제 상황: 비동기 요청의 응답 지연 시 서버가 다운되고 다른 요청도 무한 대기 상태에 빠짐.
  1. 원인: 다른 서버와의 통신 문제로 인해 응답이 지연됨.
  1. 해결책: 비동기 요청에 타임아웃 설정을 통해 AsyncRequestTimeoutException을 발생시키고 이를 처리하여 서버가 다운되는 현상을 방지.
  1. 근본 원인: 방화벽 설정 문제로 인해 다른 서버에서 백오피스 서버로의 요청이 막힘.

고민해볼 문제

  1. 타임아웃 설정 강화: 비동기 요청의 타임아웃 설정을 환경 변수나 설정 파일로 외부화하여 쉽게 조정
  1. 모니터링 및 알림: 비동기 요청의 타임아웃이나 실패 시 모니터링 및 알림 시스템을 구축하여 신속하게 문제를 파악하고 대응.
  1. 방화벽 설정 확인: 다른 서버와의 통신 문제가 발생하지 않도록 방화벽 설정을 정기적으로 테스트
 
Share article

vlogue