관리 메뉴

피터의 개발이야기

[Spring Gateway] 308 영구 리다이렉션 병목현상 해결 본문

Programming/Spring

[Spring Gateway] 308 영구 리다이렉션 병목현상 해결

기록하는 백앤드개발자 2023. 8. 1. 17:13
반응형

ㅁ 개요

  Spring Cloud Gateway 로그 상에서 308 PERMANENT_REDIRECT 상태 코드가 지속적으로 발견되었다. 이를 모니터링하고 원인을 분석하는 과정을 정리하였다.

 

 

ㅁ Http status Code

 Http Status Code는 크게 다섯 가지 HTTP 상태 코드 범주(또는 클래스)가 있다. 각각은 서버에서 브라우저로의 다른 응답을 나타낸다.

 

  • 1XX — 정보 코드 : 서버가 요청을 확인하고 처리 중이다.
  • 2XX — 성공 코드 : 서버가 요청을 성공적으로 수신, 처리하였다.
  • 3XX — 리디렉션 코드 : 서버가 요청을 받았지만 다른 곳으로 리디렉션된다.
  • 4XX — 클라이언트 오류 코드 : 서버가 페이지 또는 웹사이트를 찾을 수 없거나 연결할 수 없다. 이것은 사이트 측의 오류이다. 
  • 5XX — 서버 오류 코드 : 클라이언트가 유효한 요청을 했지만 서버가 요청을 완료하지 못하였다. 

 

ㅁ 30X : Redirection messages

CODE NAME DESC
300 Multiple Choice
여러 선택항목
선택 항목이 여러 개 있다.
지정한 URI에 대해서 콘텐츠 협상을 수행한 결과 서버에서 콘텐츠를 결정하지 못하고 클라이언트에게 복수 개의 링크를 응답할 때 사용한다.클라이언트는 요청을 마치기 위해 추가 동작을 취해야 한다.
301 Moved Permanently
영구 이동
지정한 리소스가 새로운 URI로 이동하였다.
이동할 곳의 새로운 URI는 응답 헤더 Location에 기록합니다.
302 Found
다른 위치 찾음
요청한 리소스를 다른 URI에서 찾았다.
요청한 URI가 없으므로 클라이언트 메소드를 그대로 유지한 채 응답 헤더 Location에 표시된 다른 URI로 요청을 재송신할 필요가 있다. 302의 의미를 정확하게 개선해서 307을 정의하였으므로 이 응답 코드의 사용은 권장하지 않는다.
303 See Other
다른 위치 보기
다른 위치로 요청하라.
요청에 대한 처리 결과를 응답 헤더 Location에 표시된 URI에서 GET으로 취득할 수 있습니다. 브라우저의 폼 요청을 POST로 처리하고 그 결과 화면으로 리다이렉트시킬 때 자주 사용하는 응답 코드이다.
304 Not Modified
수정되지 않음
마지막 요청 이후 요청한 페이지는 수정되지 않았다.
If-Modified-Since와 같은 조건부 GET 요청일 때 지정한 리소스가 갱신되지 않았음을 알려 준다. 이 응답 코드에는 바디가 없다.
305 Use Proxy
프록시 사용
지정한 리소스에 액세스하려면 프록시를 통해야 한다.
응답 헤더 Location에 프록시의 URI를 기록한다.
306 Unused
미사용
예전 버전에서 사용하다가 현재는 사용하지 않는 상태 코드이다.
307 Temporary Redirect
임시 리다이렉션
임시로 리다이렉션 요청이 필요하다.
요청한 URI가 없으므로 클라이언트 메소드를 그대로 유지한 채 응답 헤더 Location에 표시된 다른 URI로 요청을 재송신할 필요가 있다. 클라이언트는 향후 요청 시 원래 위치를 계속 사용해야 한다. 302의 의미를 정확하게 재정의해서 HTTP/1.1의 307 응답으로 추가되었다.
308 Permanent Redirect
영구 리다이렉션
이것은 리소스가 이제 HTTP 응답 헤더의 Location:에 명시된 영구히 다른 URI에 위치하고 있음을 의미한다. 이것은 301 Moved Permanently HTTP 응답 코드와 동일한 의미를 가지고 있으며, 사용자 에이전트가 반드시 HTTP 메소드를 변경하지 말아야 하는 점만 다르다. 만약 첫 요청에 POST가 사용되었다면, 두번째 요청도 반드시 POST를 사용해야 한다.

 

  3xx HTTP 상태 코드란 재지정 그룹에 속한다. 예를 들어 페이지를 보려고 링크를 클릭하면 브라우저가 서버에 연결을 요청한다. 서버는 이에 대해 응답을 돌려보낸다. 이 때 원하는 웹사이트가 이전을 하는 등 문제로 존재하지 않는다면 서버는 “당신이 원하는 페이지는 여기에 없으니 어디로 이동해라”는 응답을 내보낸다.

 

  301 302 307 308
Permanent(영구성) O X X O
Same Method X X O O

 

  URL이 리다이렉트 되었을 때, 최초의 요청 방법 (GET or POST)을 유지하지 않고 무조건 GET으로 변경시키면서 리다이렉트 시키는것이 301 또는 302이고, 원래의 method (GET, POST)를 유지하면서 리다이렉트 시키는 것이 307 또는 308이다. 이중에서 "308 Permanent Redirect"은 임시가 아니라 영원히 리다이렉트 되었다는 의미이다.

 

 

ㅁ Gateway와 Front서버의 병목현상 확인

 Gateway trace 로그에서 308 영구 리다이렉션이 지속적으로 발생하였다. 무한 리다이렉션으로 인해 처리속도(elapsed_time)이 1초 이상 소요되는 상황이 발생하였다.

 

Request failed with status code 404

  at createError (node_modules/axios/lib/core/createError.js:16:15)
  at settle (node_modules/axios/lib/core/settle.js:17:12)
  at Unzip.handleStreamEnd (node_modules/axios/lib/adapters/http.js:269:11)
  at Unzip.emit (node:events:394:28)
  at endReadableNT (node:internal/streams/readable:1343:12)
  at processTicksAndRejections (node:internal/process/task_queues:83:21)

  Front 서버에서도 에러코드가 발생하고 있었고, 시간이 지날수록 무한 리다이렉션이 중첩되면서 응답속도는 더욱 늦어졌다. 그래서 2시간이 지나면 개발 FrontEnd 서버를 재기동 해야만 했다.

 

 

ㅁ 무한 루프의 고리를 찾아서...

 Spring Cloud Gateway에서는 authentication 모듈과 통신하여 토큰을 체크하고 없는 경우 로그인페이지로 리다이렉션을 시키고 있는데, 일부 Front에서 호출하는 API에서 토큰 정보가 없었다.

 

  Front Main(토큰정보 없음) 요청 -> Gateway Redirection -> Front Main(토큰정보 없음) 요청 gateway 

 

결국 요청을 주는 Front 소스를 확인한 결과, API 호출 후 Exception에 대한 catch문이 없었다. 다시 말해 Http Status 308에 대한 방어 로직이 되어 있지 않아 다시 Gateway에 요청을 보내면서 무한 리다이렉션이 발생하였다.

 

 

반응형
Comments