세션 불일치 문제 해결방법

sieun·2021년 7월 26일
3
post-thumbnail

개요

e-commerce 대용량 서버 프로젝트에서 세션 방식으로 로그인을 구현하는데, 이전 글에서 언급했듯이 스케일 아웃을 적용하였습니다. 스케일 아웃으로 서버의 저장소가 여러 대로 분산되면서 로드밸런싱을 통해 부하를 분산 처리해야 하는데, 이 때 세션 불일치 문제가 발생하는 것을 알 수 있었습니다. 이러한 세션 불일치 문제를 해결하는 방법에는 무엇이 있으며 프로젝트에 어떤 방식을 적용하는 것이 적합할지 알아보려고 합니다.


세션 불일치 문제의 배경


서비스를 사용하려는 사용자가 로그인했다는 상황을 가정해보겠습니다.

1. 요청
스케일 아웃의 경우 서버가 여러 대로 일을 나누어 처리하기 때문에, 로드밸런싱 전략을 통해 사용자의 요청이 여러 서버 중 하나의 서버로 전달됩니다.

2. 세션 저장
요청을 받은 서버를 Server1이라고 한다면, Server1에는 사용자의 로그인 정보가 담긴 세션이 저장됩니다.

3. 로그인 성공
해당 세션의 sessionid와 함께 로그인이 성공했다는 응답을 사용자에게 전달됩니다.

4. 요청
사용자가 서비스의 다른 기능을 사용하려고 요청을 보내면, 다시 로드밸런싱 전략에 의해 하나의 서버로 전달되는데, 이 때 사용자의 로그인 세션 정보가 존재하는 Server1으로 들어간다는 보장이 되지 않습니다.

5. 세션 조회 실패
세션이 저장된 서버 외의 다른 서버로 요청이 전달된다면 사용자가 요청 헤더에 넣은 sessionid로 조회가 불가능하기 때문에 로그인이 풀리는 현상이 발생합니다.

이렇게 스케일 아웃에서 발생할 수 있는 세션 불일치 문제를 해결하기 위해서는 분산된 세션 데이터를 관리하는 기술이 필요합니다.


해결 방법

1. Sticky Session


Sticky Session은 사용자의 세션을 처음 생성한 서버가 해당 사용자의 작업을 담당하여 고정된 세션만 사용하는 전략입니다.
즉, User1Server1에서 처음 로그인 요청을 하여 세션을 생성하였다면, 앞으로의 모든 User1의 요청은 Server1에만 보내지게 됩니다.

이렇게 특정 사용자의 요청을 하나의 서버로 고정시키기 위해서 로드밸런서는 요청을 보낸 사용자의 IP주소나 쿠키를 이용합니다. IP tracking 또는 쿠키를 사용하는 방식으로 로드밸런서는 해당 사용자의 요청이 보내져야하는 고정된 서버를 확인하며, 그 후에 요청을 지정된 서버로 보냅니다.
Sticky Session의 예시로 ELB(Elastic Load Balancing)를 들 수 있는데, 이것은 AWS(아마존 웹 서비스)에서 제공하는 로드밸런싱 서비스입니다. ELB를 통해서 각 인스턴스에 접속한 사용자를 지속적으로 처리할 수 있도록 해줍니다.

결론적으로 Sticky Session방식으로 사용자는 세션이 유지되는 동안 하나의 서버만 사용하게 되므로 세션 불일치 문제가 발생하지 않습니다.

Sticky Session의 단점


1. 세션 정보를 잃어버릴 수 있다.
특정 서버에 장애가 발생하여 다운되면 해당 서버로 요청을 보내는 사용자의 세션 정보를 잃어버리게 됩니다. 로드밸런서는 트래픽을 다운된 서버를 제외하고 나머지 서버로 보내게 되는데, 결국 다시 로그인 해야하는 상황이 발생합니다. 또, 다운된 서버가 다시 구동되더라도 이미 다른 서버로 분산된 세션 정보가 돌아오지 않아 다른 특정 서버에 트래픽이 집중될 수 있습니다.

2. 특정 서버에 트래픽이 몰릴 수 있다.
1번과 같은 상황으로 인하여 특정 서버에 트래픽이 집중될 수 있습니다.
또한 활발하게 서비스를 사용하는 사용자가 하나의 서버에 몰리게 되는 상황에서도 과부하가 발생할 수 있습니다. 이는 각 접속마다 적절하게 서버에 분산되어 할당되는 것이 아니라 특정 서버로만 할당하기 때문입니다.
사설 IP를 사용하는 장비들이 공인 IP로 바꾸어 네트워크 통신을 하는 경우를 예로 들 수 있는데, 대기업 회사의 천 명이 넘는 사원들이 같은 공유기를 사용한다고 가정해봅시다.
이 때, Sticky Session이 IP주소의 패턴을 기준으로 맵핑을 시키게 되면 같은 내부망에 있는 많은 사용자가 동일한 공인 IP를 갖게 되어 한 번에 한 서버에만 요청이 들어가기 때문에 트래픽이 몰릴 수 있습니다.

공인IP는 인터넷 상에서 서로 다른 PC끼리 통신하기 위한 단 하나뿐인 IP이며, 사설IP는 공유기와 같이 내부 네트워크 상에서 각 컴퓨터 간의 통신을 위한 내부망 전용 IP입니다. 사설IP들은 라우터를 통해 하나의 공인IP 할당받고 라우터에 연결된 개인 컴퓨터는 사설IP를 각각 할당 받아 인터넷에 접속할 수 있게 되는 것입니다.


2. Session Clustering

클러스터링은 여러 대의 컴퓨터 혹은 서버들이 연결되어 하나의 시스템처럼 동작하는 것을 의미합니다. WAS에 따라서 Session Clustering방식이 다른데, 그 중에서도 스프링 부트의 내장 WAS인 Tomcat의 Session Clustering 방식을 확인해보겠습니다.
Tomcat 공식문서에는 다음과 같이 설명되어 있습니다.

즉, Tomcat은 Session Clustering을 구현하는 방법으로 all-to-all세션 복제 방식을 사용하며, 해당 방식은 모든 세션이 클러스터의 다른 모든 노드에 복제되는 방법입니다.

사용자의 세션이 새로 생성되거나 업데이트 될 때마다 Tomcat에서 DeltaManager가 다른 모든 서버에 해당 세션의 정보를 복제합니다.
그렇게 되면 사용자의 요청이 처음 세션을 생성한 서버가 아닌 다른 서버로 보내졌어도 모든 서버에는 사용자의 세션 정보를 가지고 있어 세션 불일치 문제가 발생하지 않습니다.

Session Clustering의 단점


1. 많은 메모리가 필요하다.
데이터가 변경될 때마다 세션의 데이터가 복제되기 때문에 서버의 수가 늘어날수록 많은 메모리를 필요로 합니다. 그렇기 때문에 위의 공식문서의 내용과 같이 4대 이상의 대규모 클러스터는 권장되지 않습니다.

2. 성능 저하가 발생한다.
마찬가지로 세션 데이터가 변경되면 모든 서버에 복제되므로 서버 수의 비례하여 네트워크 트래픽이 증가합니다. 그로인해 성능 저하가 발생할 수 있습니다.

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

4. 새로운 서버가 생겨나면 클러스터링을 해주어야 한다.
새로운 서버를 띄울 때마다 기존에 존재하던 WAS에 새로운 서버 IP/포트를 입력하여 클러스터링 해주어야 합니다. 그로 인하여 새로운 서버를 띄우면 기존 서버의 수정이 발생하고, 에러가 생길 가능성도 생겨나게 됩니다.


3. Session Storage

Session Storage방식은 독립된 세션 저장소를 구성하여 해당 저장소에 세션 데이터를 저장하고, 여러 서버들이 이러한 독립된 세션 저장소에서 세션 데이터를 읽어오는 방식입니다.


Session Storage가 분리되면 서버가 늘어나도 외부 저장소의 정보만 각각의 서버에 입력해주면 데이터를 읽어올 수 있습니다. 그렇기 때문에 특정 서버로 트래픽이 몰리는 문제가 발생하지 않으며, 하나의 독립된 저장소에서 세션을 공유하므로 대규모 클러스터 환경에서 성능을 향상시킬 수 있습니다. 세션이 재설정되어도 세션 저장소에 있는 데이터만 수정하면 되어 WAS간의 네트워크 통신이 필요하지 않기 때문입니다.
또한 여러 서버가 하나의 세션 저장소를 사용하므로 세션 불일치 문제를 해결할 수 있습니다.

Session Storage의 단점


1. 세션 저장소가 다운되면 세션 정보를 잃어버릴 수 있다.
하나의 독립된 세션 저장소에서 세션 데이터를 저장하고 있기 때문에 해당 저장소가 다운되면 모든 서버가 세션을 공유받을 수 없습니다.
그래서 세션 저장소에 장애가 발생하면 모든 서버에서 세션을 사용할 수 없게 됩니다.
때문에 동일한 세션 저장소를 하나 더 구성하여 복제해야 할 필요가 있습니다.


결론

진행중인 e-commerce 프로젝트는 전세계 사용자의 요청을 받는다는 가정하에 설계되었기 때문에 서버의 개수를 여럿 늘릴 수 있고, 트래픽이 몰려 과부하가 발생할 가능성이 적은 Session Storage방식이 적합하다고 판단하였습니다.

✅ 이후에는 세션 저장소에는 무엇이 있는지 살펴본 후에, 프로젝트에 적합한 저장소에 대해서 트레이드 오프를 고려한 결과를 올릴 예정입니다.
✅ 로드밸런서와 그 전략에 관해서도 다시 한 번 다뤄볼 생각입니다.



📕Reference

https://aws.amazon.com/ko/blogs/aws/new-elastic-load-balancing-feature-sticky-sessions/
http://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html
https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#spring-cloud-loadbalancer-hints

profile
열심히 공부중입니다😇

0개의 댓글