[ReSeller Project] Scale out 확장 구조에서 Session 불일치 문제를 어떻게 다뤄야 할까 🤔

홍정완·2022년 9월 2일
0

ReSeller Project

목록 보기
6/15
post-thumbnail

저번 포스팅에서는 서버의 확장은 어떤 것들이 있는지 Scale up vs Scale out 비교를 통해 살펴보았다.


이때, Scale out을 통해 여러 대의 서버로 요청을 처리하도록 분산 서버 환경을 만들면 각 서버 별로 로그인 세션 정보가 다른 세션 불일치 문제가 발생한다.

이번 포스팅에서는 Session 불일치 문제를 어떻게 다뤄야 할지, 대표적인 방법들을 살펴보며 고민해 보자.



세션의 불일치가 무슨 뜻일까?


단일 서버 환경에서는 session을 통한 로그인을 구현할 때 session 불일치 문제를 신경 쓸 필요가 없었다.

하지만 트래픽이 증가함에 따라 scale-out 방식을 적용해 서버를 여러 대 늘렸다고 가정해 보자.
이때 발생하는 문제점 중 하나가 바로 세션 불일치 문제다.


먼저 3대의 서버 중 서버 1에서 로그인을 진행했다. 이 경우, 서버 1에서는 해당 클라이언트의 login session이 존재하지만, 서버 2와 서버 3에서는 해당 클라이언트의 login session이 존재하지 않는다.

어느 한 서버로 요청을 보내 서버에 세션 정보를 생성하면 생성된 세션 정보는 해당 서버를 제외한 다른 서버에서는 모르기 때문이다.


즉, 다른 서버에서는 생성된 세션 정보를 모른다.



아래의 사진들로 과정을 살펴보자.

클라이언트가 서버 1에서 로그인한 후 주문을 하기 위해 주문 버튼을 눌렀는데,
로드 밸런서에 의해 해당 주문 작업은 서버 2로 요청되었다고 가정해 보자.



서버 2에는 해당 클라이언트의 session이 저장되어 있지 않기 때문에 서버 2는 로그인 후 이용하라는 응답을 클라이언트에게 보낸다. 유저 입장에서는 분명 로그인을 했는데 다시 로그인 요청을 받게 되는 것이다.



해결 방법


이러한 세션 정합성 문제를 해결하기 위한 방법에는 3가지가 있다.



① Sticky Session

  • 로드 밸런서가 동일한 클라이언트의 요청을 세션이 생성된 서버로만 보내도록 하는 방법

Sticky란 번역하면 끈적임, 껌딱지라는 뜻이다.
처음 작업이 요청에 대한 응답을 준 서버에서 해당 클라이언트의 작업을 담당하는 것이다.
쉽게 말해서 해당 서버에 껌처럼 붙어있다고 생각하면 된다.

서버 1에서 로그인 요청기타 다른 작업도 서버 1로 요청

위 그림처럼 클라이언트가 서버 1에서 로그인 작업을 통해 세션을 생성했다면 해당 클라이언트에 대한 앞으로의 모든 요청도 서버 1이 담당하게 되는 것이다.

로드 밸런서는 서버 계층의 앞단에 존재하며 서버로 들어오는 모든 요청이 로드 밸런서를 거쳐가게 된다. 거쳐가는 과정에서 클라이언트 요청의 쿠키 값이나 IP 세부 정보를 기반으로 동일한 클라이언트 인지 판단하고 세션이 생성된 서버로 다시 라우팅 되면서 클라이언트는 동일한 세션을 제공받을 수 있는 환경이 만들어진다.

만약 쿠키가 존재하지 않는다면 기존 로드밸런싱 방법에 의해 요청이 이루어진다.


단점

특정 서버에 트래픽이 집중되는 문제가 발생할 수 있다.

로드 밸런서가 클라이언트의 쿠키나 IP에 의해 트래픽을 처리하기 때문에 특정 조건에 의해 트래픽이 한 곳으로 몰릴 수 있고, 그렇게 된다면 Scale out의 장점인 서버의 가용성을 최대한 활용 못 하는 상황이 발생할 수 있다.


세션 정보가 유실될 수 있다.

만약 사용자의 세션 정보가 저장된 서버가 다운된다면, 로드 밸런서는 다운된 서버를 제외한 나머지 서버에 요청을 하게 될 것이다. 나머지 서버는 해당 사용자의 로그인 정보를 가지고 있지 않기 때문에 세션 불일치 문제가 발생할 수 있다.



② WAS에서 지원하는 Session Clustering

  • 세션 정보를 모든 서버에 공유하는 방법

서버 1에서 로그인 요청WAS 톰캣이 지원하는 all-to-all 방식

WAS마다 session clustering을 지원하는 방식이 조금씩 다른데, 그중 가장 대표적 WAS인 톰캣이 지원하는 방식은 all-to-all 방식으로 해당 서버에 저장된 session의 정보를 다른 서버에 전파하는 방식을 취하고 있다.


특정 서버에 생성된 세션을 클러스터를 이루는 모든 서버에 세션을 복제하기 때문에 클라이언트의 요청을 한곳으로 지정하지 않아도 되고, 다른 서버로 요청을 보내더라도 같은 세션을 유지할 수 있다. 이용하고 있는 서버에 장애가 발생해도 다른 서버에서 세션을 유지하고 있기 때문에 클라이언트는 동일한 서비스 환경을 제공받을 수 있다.


단점

대규모 클러스터에는 적합한 방식이 아니다.

세션을 모든 서버에 복제하기 위한 트래픽이 발생하고, 서버가 늘어날수록 하나의 서버가 감당해야 할 세션과 복제를 위한 트래픽이 엄청나게 증가한다.


  1. 세션을 전파(복사) 하는 작업을 진행하기 때문에 모든 서버에 동일한 세션 정보가 저장된다.
    즉, 효율적인 메모리 관리가 이루어지지 않는다.

  2. 데이터 변경이 발생할 때마다 세션을 전파(복사) 하는 작업이 일어나기 때문에 네트워크 트래픽이 증가하게 된다.

  3. 세션 전파 작업 중 모든 서버에 세션이 전파되기까지의 시간차로 인한 세션 불일치 문제와 같은 예상치 못한 문제가 발생할 가능성이 존재한다.



③ 별도의 세션 저장소를 두는 방법 (ex, redis)

  • Session 저장소를 로컬 서버에서 분리해 세션을 따로 저장하고 필요시 조회하는 방법


마지막으로 독립된 세션 스토리지로 세션을 관리하는 방법이다.

로그인이 요청된 서버에 세션 정보를 저장하는 것이 아닌 독립된 세션 저장소(서버)에 세션 정보를 저장하고, 여러 서버들이 독립된 세션 저장소에서 세션 정보를 읽어오는 방식이다.


Scale out 확장을 하더라도 세션을 저장하는 곳이 외부에 있어 세션 불일치 문제가 발생하지 않고, Sticky Session처럼 로드 밸런서를 통해 특정 트래픽을 분리할 필요가 없다.

하지만 해당 방법을 사용하면 세션 저장소를 따로 분리한 만큼 서버의 관리 포인트가 더 증가하고,
세션 저장소 서버에 장애 발생 시 세션을 사용하는 모든 서버에 영향이 끼치는 위험이 있다.




3가지 방법 모두 장단점이 있는데 어떤 것을 적용해야 될까 ❓


정답은 여러 개지만 아래의 기준으로 Session Storage를 선택하려고 한다.


  • Stateless 서버가 가지는 장점을 활용할 수 있는가

  • WAS에 장애가 발생해도 다른 서버에서 세션을 사용하는 데에 지장이 없는가

  • 서버가 늘어남에 따라 발생하는 오버헤드가 적고, 트래픽이 균등하게 분배되지 못하는 현상을 해결할 수 있는가

profile
습관이 전부다.

0개의 댓글