아리아 날다

서버가 여러 대일 때 세션 관리는 어떻게 할까? 본문

Server

서버가 여러 대일 때 세션 관리는 어떻게 할까?

Aria Park 2022. 9. 19. 02:38

들어가며

지난 포스팅에서는 Scale-Up과 Scale-Out에 대해 알아보았습니다. 서버 확장 방법이 쉬운 Scale-Up 방식을 이용하면 데이터 정합성 문제에 자유롭다는 장점이 있지만, 하나의 서버에서 모든 트래픽을 처리해야 하기 때문에 부하가 걸렸을 때 서버가 복구되기 전까지 서비스를 중단해야 하는 상황에 빠질 수 있다는 치명적인 단점이 있었습니다. 따라서 대용량 트래픽 처리와 병렬 프로그래밍이 중요한 이번 프로젝트에서는 Scale-Out 방식이 적합할 것이라고 했는데요. 오늘은 이어서 앞서 말씀드린 Scale-Out 방식에서 일어나는 세션의 데이터 정합성 문제와 해결 방법에 대해 알아보도록 하겠습니다.

 

*병렬 프로그래밍: 여러 대의 컴퓨터 또는 CPU내의 여러 코어를 사용하여 동시에 작업을 실행할 수 있도록 병렬화 하는 것


 

세션 불일치

Scale-Out은 여러 대의 서버로 트래픽을 분산 하기 때문에 로드 밸런싱(Load Balancing)이 필수적입니다. 로드 밸런싱으로 인한 분산 처리에서는 세션 불일치 문제가 발생하게 되는데요. 세션 불일치란 서버마다 가지고 있는 세션 저장소에서 세션을 공유하지 않기 때문에 발생하는 문제를 말합니다.

출처: https://velog.io/@sileeee

 

세션을 공유하지 않으면 어떤 문제가 일어날까요?

위 그림은 Session DB가 각 서버의 램 공간에서 돌아가고 있을 때의 로그인 과정 입니다. 클라이언트는 로드 밸런서를 통해 1번 서버 Session DB에 Session을 저장하고 로그인에 성공합니다. 이 후 클라이언트가 1번 서버의 Sesion ID를 쿠키에 담아 보관 하고 있다가 다시 요청을 시도합니다. 이 때 로드밸런서가 3번 서버로 요청을 보내게 되면 3번 서버에서는 Session ID를 찾을 수 없어 문제가 발생하게 됩니다. 따라서 다시 로그인해야 하는 상황이 생기게 됩니다. 이렇게 서비스에서 요청을 할 때마다 로그인을 다시 해야하는 건 클라이언트 입장에서 매우 번거로운 작업이 되므로 서비스를 이용하는 유저들이 불편함을 느끼게 될 수 있습니다.

 

웹 서비스에서 쿠키와 세션 처리는 클라이언트의 편의성과 보안 측면에서 매우 중요하게 다뤄야 하는 이슈입니다. 다중 서버 환경에서 이러한 이슈를 관리하기 위한 방법에는 크게 세가지가 있는데요. 지금부터 세션 불일치 문제 해결 방법 세가지에 대해 알아보도록 하겠습니다.

 


 

1. Sticky Session

 

이름 그대로 세션이 관리되는 곳이 한 서버에 달라 붙어있는 방식입니다. 클라이언트의 세션 요청을 맨 처음 처리한 서버로만 전송해서 첫 Request에 대해 응답을 한 서버에서만 세션이 관리됩니다. 맨 처음 1번 서버에 요청을 했다면 로드 밸런서가 그 후 요청들 모두 1번 서버로 보내 세션을 관리하게 합니다. 사용자의 요청을 하나의 서버로 고정시키기 위해서 로드밸런서는 요청을 보낸 사용자의 IP주소나 쿠키를 사용합니다. IP tracking과 같은 방식으로 로드 밸런서는 해당 사용자의 요청이 보내져야 하는 고정된 서버를 확인하며, 그 후에 요청을 지정된 서버로 보냅니다.

 

 

한 서버에서만 세션을 관리해주면 불일치 문제가 해결되는 것 아닌가요?

맞습니다. 하지만 한 서버에만 계속 요청을 보내서 생기는 문제는 없을까요?

 

Sticky Session 단점

특정 서버에 장애가 발생해 다운되면 해당 서버로 요청을 보내는 사용자의 세션 정보를 잃게 됩니다. 로드 밸런서는 다운된 서버를 제외하고 나머지 서버로 연결하는데 이 때 결국 다시 로그인 해야 하는 상황이 발생합니다. 또, 활발하게 서비스를 사용하는 사용자가 하나의 서버에 몰리게 되는 상황에서 과부하가 발생할 수 있습니다. 분산 서버의 장점을 활용하지 못하고 특정 서버로만 할당되기 때문에 특정 서버에 트래픽이 몰리게 될 수 있습니다. 

 

그렇다면 왜, 어떤 경우에 한 서버에 몰리는 일이 발생하는 걸까요?

부하 분산에는 L4/L7 로드 밸런싱을 많이 사용합니다. L4스위치는 로드 밸런싱을 처리하는 장비로, 외부에서 들어오는 모든 요청은 서버가 아닌 L4 스위치를 거쳐야 합니다. 이 때 L4스위치에 있는 Sticky라는 옵션을 활성화 시키면 로드 밸런서는 timeout 시간 내에 재접속한 동일 사용자가 같은 서버로 접속할 수 있도록 할당해 줍니다. 이런 경우에 세션을 유지할 수 있지만 각 접속마다 적절하게 분산 처리 하는 것이 아니기 때문에 같은 내부망에 있는 사용자가 동일한 외부IP를 갖게 되는 상황에서는 트래픽이 몰릴 수 있습니다.

 

 


 

2. Session Clustering

Clustering은 여러 대의 컴퓨터나 서버들이 연결되어 하나의 시스템처럼 동작하는 것을 의미합니다. Session Clustering은 WAS에 따라서 그 방식이 다른데 대표적으로 Tomcat은 Session Clustering을 위해 all-to-all 세션 복제 방식을 사용합니다. 사용자의 세션이 새로 생성되거나 업데이트 될 때마다 Tomcat의 DeltaManager가 다른 모든 서버에 해당 세션의 정보를 복제 합니다. 이렇게 되면 모든 서버가 사용자의 세션 정보를 가지게 되므로 다른 서버로 요청하더라도 세션 불일치 문제를 해결 할 수 있습니다.

 

모든 서버가 세션 정보를 가지게 되면 한 서버가 끊겨도 상관 없으니 Sticky Session의 문제점도 보완할 수 있는 것 아닌가요?

맞습니다. 하지만 세션이 복제되면 메모리는 어떻게 될까요?

 

Session Clustering 단점

새로운 서버가 추가 될 때마다 기존 WAS에 새로운 IP/Port를 입력해서 클러스터링 해줘야 하는 방식이기 때문에 기존 서버의 수정이 필요해 에러가 발생할 수 있습니다. 데이터가 변경 될 때마다 세션이 복제되기 때문에 서버의 수가 늘어날 수록 많은 메모리를 필요로 하고, Tomcat 공식문서에서는 4대 이상의 대규모 클러스터는 권장되지 않는다고 명시되어 있습니다. 또 서버 수에 비례해 네트워크 트래픽이 증가할 가능성이 높고 이로 인한 성능저하 문제가 발생할 수 있으며 세션 데이터의 복제 작업 중에 모든 서버에 세션이 전파되기 전까지의 시간차로 세션 불일치 문제가 일어날 수 있습니다.

 


3. Session Storage

각각의 서버에 세션 정보를 저장하는 것이 아니라 외부에 저장소를 만들고 이 서버에 모든 데이터를 저장하는 방식입니다. 특정 서버로 트래픽이 몰리는 문제가 발생하지 않고, 하나의 독립된 저장소에서 세션을 공유하므로 대규모 클러스터 환경에서 성능을 향상시킬 수 있습니다. 세션이 재설정 되어도 세션 저장소에 있는 데이터만 수정하면 되기 때문에 WAS간의 네트워크 통신이 필요하지 않다는 장점도 있습니다.

 

Sticky Session과 Session Clustering이 가진 문제점을 해결하고 세션 불일치 문제도 일어나지 않는 방법 아닌가요?

맞습니다. 하지만 모든 세션 정보를 포함하고 있는 Storage가 다운되면 어떻게 될까요?

 


 

In- memory DB, Redis와 Memcached 

출처: https://db-engines.com/en/ranking_trend

 

위 그래프는 Key-value 저장 방식의 DB엔진 순위를 나타냅니다. 하늘색과 주황색 그래프를 보면 Redis와 Memcached 모두 상위권에 위치하고 있는 것을 알 수 있습니다. 그렇다면 각각 무엇이고 어떤 차이가 있는지 또, 이번 프로젝트에서는 어떤 데이터 베이스를 고려하면 좋을 지 알아보겠습니다.

 

Redis

Storage가 다운돼 모든 세션이 날아가는 것을 방지하기 위해 우리는 Redis의 Replication을 고려해 볼 수 있습니다. Redis는 모든 데이터를 메모리에 저장하고 조회하는 in-memory DB로 다양한 기능을 제공합니다. 그 예로 다양한 자료구조와 용량, 삭제 정책, 영속화, 복제, 트랜잭션이 있습니다. 여기서 복제는 하나의 인스턴스로부터 또 다른 레플리카 인스턴스를 복사하는 것입니다. 목적은 데이터의 복제본이 또 다른 인스턴스에 유지되는 것이고 이를 이용해 세션 Storage가 날아가는 것을 방지하는 것입니다.

 

Memcached

또 다른 in-memory DB인 Memcached는 데이터 베이스 호출, API 호출 또는 페이지 렌더링 결과의 데이터 청크를 위한 메모리 내 Key-value 저장소 입니다. Memcached는 분산 메모리 캐시 시스템으로 RAM에 데이터 및 오브젝트를 캐시해 데이터베이스 및 API에서 읽어와야 하는 횟수를 줄여줍니다. 또, 멀티쓰레드를 지원해 처리 속도가 빠르지만 Redis와 비교했을 때 Replication기법이 없다는 차이가 있습니다. Memcached는 직렬화된 형태로 데이터를 저장해 읽기 전용인 데이터를 저장하기 좋다는 장점이 있지만, 쉽게 확장이 가능한만큼 해싱 사용 여부에 따라 캐시 된 데이터의 일부 혹은 전부까지 잃게 될 수 있다는 특징이 있습니다. 

 

결론

이번 프로젝트에서는 대용량 트래픽 처리가 핵심이고,  메모리 공간의 최소화를 목표로 하고 있습니다. 거기에 Scale-Out 방식의 서버 확장에서 일어날 수 있는 세션 불일치 문제를 해결할 수 있어야 하기 때문에 가장 효율적으로 세션을 보관 할 수 있는 Session Storage 방법을 선택하게 되었는데요. Redis를 사용하면 Memcached에 비해 다양한 기능을 지원하기 때문에 개발의 편의성 또한 증가할 것이라고 예상했고, 싱글 쓰레드로 동작하는 서버의 모든 자료구조는 Atomic하기 때문에 레디스가 교착상태(Race Condition)를 피해 데이터의 정합성을 보장하기 쉽다는 장점도 있어 선택하게 되었습니다. 이는 트랜잭션 문제 또한 중요하게 다루게 될 이번 프로젝트에서 가장 큰 이점이 될 것이라고 생각했습니다. 

 

 


 

마무리

이번 포스팅에서는 Scale-Out 방식에서 일어날 수 있는 세션 불일치를 해결할 수 있는 세가지 방법에 대해서 알아보았습니다. 여러 특징들을 고려했을 때 Session Storage방식이 가장 적합할 것이라는 결과가 나왔고, In-memory DB 중에서도 Redis의 다양한 기능을 이용해 개발의 편의성을 높일 계획입니다. 

 

 

참고

https://aws.amazon.com/ko/elasticache/what-is-redis/

 

Redis란 무엇입니까? – Amazon Web Services(AWS)

Redis 개발자는 백 개가 넘는 오픈 소스 클라이언트를 사용할 수 있으며, Java, Python, PHP, C, C++, C#, JavaScript, Node.js, Ruby, R, Go를 비롯한 다수의 언어가 지원됩니다.

aws.amazon.com

https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html

 

Apache Tomcat 8 (8.5.82) - Clustering/Session Replication How-To

Simply add to your or your element to enable clustering. Using the above configuration will enable all-to-all session replication using the DeltaManager to replicate session deltas. By all-to-all, we mean that every session gets replicated to all the other

tomcat.apache.org

https://db-engines.com/en/ranking_trend

 

historical trend of the popularity ranking of database management systems

 

db-engines.com

 

Comments