[SSE] Spring SSE 트러블 슈팅 삽질 모음

sju3358·2024년 8월 21일
0

삽질 일기

목록 보기
6/6

1. Subscribe 되자 마자 연결종료 되는 현상

SSE는 text/event-stream 형식으로 HTTP 통신을 한다.
이때, content의 길이는 정해지면 안되고, transfer-encoding은 chunked가 되어야한다.

하지만 나의 경우, Request/Response에 대한 자세한 로깅을 위해 ContentCachingRequestWrapper 필터를 사용하고 있었는데, 여기서 Content Length를 구하는순간, Wrapping된 Request / Response의 Content-Length에 ~~한 값이 찍히게 된다 (이부분은 코드를 까봐야 알듯)

따라서 필터를 탈때 분기를 해야한다.
나는 필터내에서 처리해주었다.

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

    if (request.getHeader("accept") != null && request.getHeader("accept").contains("text/event-stream")) {
      filterChain.doFilter(request, response);
      return;
    }

    ContentCachingRequestWrapper wrappingRequest = new ContentCachingRequestWrapper(request);
    ContentCachingResponseWrapper wrappingResponse = new ContentCachingResponseWrapper(response);
    filterChain.doFilter(wrappingRequest, wrappingResponse);
    wrappingResponse.copyBodyToResponse();
  }

2. 반복해서 연결이 끊기는 문제 (net:ERR_HTTP2_PROTOCOL_ERROR)

ALB 혹은 NGINX에서 타임아웃이 난것이다.
SSE는 웹소켓이 아닌 HTTP 프로토콜을 사용하므로,
ALB나 NGINX에서 HTTP프로토콜에 대해서 타임아웃 설정이 되어있다면
아무리 keep-alive나 어떠한 헤더를 추가한다 하더라도 타임아웃이 발생한다.

이 경우는 타임 아웃 제한시간을 늘려주면 되는데, 그렇게 해버리면 다른 SSE가 아닌 REST API에 대해서도 똑같이 적용되어 Content-Type에 따라 분리 해야한다.

근데 어차피 이 SSE통신을 받는 주체가 여러명의 사용자가 아닌, 1명의 사용자이므로 (백오피스 대시보드 알림용이라...) 1분마다 연결재요청을해도 대충 계산때려보니 한달에 2만원 +-정도의 요금이 발생하므로 그냥 그대로 두었고,

재연결시 유실된 이벤트를 받아오는 식으로 로직을 구현하려고 한다.

profile
주니어 백엔드 개발자의 삽질 일기장

0개의 댓글