[Infra] 대용량 트래픽 대응 - 2. 세션 불일치의 문제 및 해결방안

2022. 8. 11. 16:38토이프로젝트/팁 모음집

  • 앞서 서버의 성능을 높이는 방법으로 스케일 업과 스케일 아웃에 대해 알아보았다.
  • 그리고, 스케일 아웃으로 방향을 정했을 때 고민해야 하는 문제는 세션 불일치에 대한 문제이다.
  • 그에 앞서 세션이 무엇인지에 대해 간략하게 알아보자면,
※ 쿠키와 세션
▽ 사용 이유 : HTTP 프로토콜의 특징이자 약점을 보완하기 위해서이다.
① Connectionless 프로토콜 (비연결지향)
- 만일, 클라이언트가 서버로 요청을 보냈을 때, 그 요청에 맞는 응답을 보낸 후 연결을 끊는 처리 방식이다.
- 이 부분은 HTTP 1.1 버전에서 연결을 유지하고 재활용하는 기능이 default로 추가되었다. (keep-alive 값으로 변경 가능)
② Stateless 프로토콜
- 클라이언트의 상태 정보를 서버 측에서 가지지 않는다.
- 만일 클라이언트와 첫 번째 통신으로 데이터를 주고 받았다고 해도, 두 번째 통신에서 그 데이터를 유지하지 않음.
▽ 그러나, 실제로는 데이터 유지가 필요하다. 예를 들자면 페이지를 이동할 때마다 로그인을 다시 하거나 상품을 선택했는데 구매 페이지에 선택한 상품의 정보가 없으면 곤란하다. 따라서, 이러한 상황에 대한 대처로 쿠키과 세션을 사용한다.
▷ 쿠키(Cookie) : 어떠한 서버에서 클라이언트의 컴퓨터에 기록하는 작은 기록 정보 파일이다.
▷ 세션(Session) : 일정 시간 동안, 같은 사용자로부터 들어오는 일련의 요청들을 하나의 상태로 보고 그 상태를 일정하게 유지시키는 기술이다. 보안 면에서 쿠키보다 뛰어나다.

 

※ 왜 세션 불일치가 일어나는가?

  • 세션은 key와 value로 이루어진, 서버의 저장소인데, scale out 방식을 차용해 서버가 여러 대 있다고 가정해보자.

  • session db가 각 서버에 위치하고 있다고 가정한다.

위 그림의 클라이언트가 로그인을 하게 되면 거치는 과정은 다음과 같다.

  1. 클라이언트가 로드밸런서를 거쳐 1번 서버에서 session Id를 발급받았다.
  2. 클라이언트는 1번 서버의 session Id를 쿠키에 담아서 가지고 있다.
  3. 클라이언트는 그 다음 요청으로 로드밸런서를 거쳐 2번 서버에 도달한다.
  4. 2번 서버에서는 1번 서버의 session db를 알 방도가 없으므로 찾을 수가 없게 되고, 로그인 세션이라고 가정했을 경우 로그인을 다시 해주어야 하는 상황이 발생한다.

 

※ 해결 방안은 어떤 것이 있는가?

  • 요구되는 것은 사용자가 요청을 보낼 때 자신의 session Id가 session db에 무조건 있는 상황이다.
  • Sticky Session, Session Clustering, 그리고 별도의 session을 관리하는 저장소를 두는, 즉 기존 서버에서 분리하는 방법이 있다.

① Sticky Session

  • Sticky Session의 경우 응답을 준 서버에만 세션이 관리되고, 요청 또한 특정 세션의 요청을 처음 처리한 서버로만 보내게 된다.
  • 이렇게 수많은 요청들을 구분지어 요청을 처음 처리한 서버로 보내게 될 수 있는 이유는 중간의 로드밸런서 때문이다.
  • 로드밸런서는 요청을 구분지을 때 보내줘야 할 인스턴스를 찾기 위해 쿠키 정보를 활용하게 된다. 만약 요청을 받는다면, 우선적으로 요청에 쿠키 정보가 있는지를 확인하고 로드 밸런서에 의해 해당 요청은 그 쿠키가 생성되어 있는 인스턴스로 보내진다. 만일 존재하지 않는 쿠키라면 로드 밸런서의 알고리즘에 의해 인스턴스가 선택되어 쿠키가 생성되고 다음 요청도 그 인스턴스 경로로 매핑되어 보내진다.

하지만 Sticky Session의 사용은 지양하는 것이 좋다. 왜일까?

  1. 애플리케이션이 쉽게 다운될 수 있다. 만일 서버 중 하나가 고장났다면 HDD와 같은 영구 저장소를 사용하더라도 다른 서버에서 이 데이터로 액세스가 불가능하고, 애플리케이션 메모리를 상태 저장소로 사용하게 되면 서버 재시작 시에 이 서버의 세션이 바인딩 된 모든 데이터가 손실된다.
  2. 애플리케이션의 올바른 확장이 불가능하다. 서버를 특정 요청에 바인딩할 때 다른 서버의 용량을 사용해 부하를 올바르게 나눌 수 없고, 만일 특정 세션에서 CPU 집약적인 작업을 수행한다고 가정하면 인프라의 한 인스턴스가 모든 일을 처리하도록 강제한다.
  3. DOS 공격에 취약해질 수밖에 없다.

 

② Session Clustering

  • Clustering(클러스터링) : 여러 대의 컴퓨터 혹은 서버들이 네트워크로 연결되어 마치 하나의 시스템처럼 동작하는 것을 뜻함
  • Tomcat을 예로 들자면, 새로 세션이 생성되었거나 세션 정보가 변경될 때마다 Tomcat에서 세션을 제어하고 세션 복제를 처리하는 DeltaManager가 클러스터로 묶인 다른 모든 서버에 이와 동일한 세션 데이터를 복제한다.
  • 이러한 방식은 세션에 대한 변경이 일어날 때마다 세션을 복제해야하기 때문에 사용자 수가 많은 상황에서는 성능 면에서 효율적이지 못하다.

 

③ 세션 저장소 분리

  • 각 서버는 분리된 세션 저장소에 대한 정보만 알고 있으면 되기 때문에 서버를 추가하거나 삭제하는 것이 용이해진다.
  • 위에서 언급되었던 Sticky Session 방식처럼 세션이 처음 생성된 서버에 따라 로드밸런서에 의해 트래픽이 분배되는 것이 아니므로 특정 서버에 과부하가 몰려 생기는 좋지 않은 상황은 발생할 가능성이 적다.
  • 하나의 저장소에서 모든 서버의 세션을 공유하는 방식이기 때문에 데이터 정합성 문제나 세션 클러스터링 방식의 한계점도 해결된다.
  • 그러나, 하나의 저장소를 사용하여 세션을 관리하기 때문에 해당 저장소가 다운되면 모든 서버가 세션을 사용할 수 없다는 문제점이 있다.
  • 다음 포스팅으로는 과연 이 세션 저장소로 On-disk Database와 In-memory Database 중 어느 것이 적합할지 알아보도록 한다.

 

 

[출처]

https://dev.to/gkoniaris/why-you-should-never-use-sticky-sessions-2pkj