dev-sohee 님의 블로그

서버 간 세션 불일치 문제, 이렇게 해결한다(Sticky Session, Session Clustering, In-Memory DB) 본문

서버 간 세션 불일치 문제, 이렇게 해결한다(Sticky Session, Session Clustering, In-Memory DB)

dev-sohee 2024. 8. 24. 14:08

세션 불일치 문제는 단일 서버 환경에서는 발생하지 않으므로 따로 걱정하지 않아도 됩니다. 하지만, 최근 웹 서비스는 일반적으로 수평 확장된 다중 서버 환경일 것입니다. 이런 다중 서버 환경에서는 세션 불일치 문제가 발생할 수 있습니다. 기본적으로 세션은 서버의 물리적 메모리(RAM)에 저장되기 때문입니다.

예를 들어, 서버를 수평적으로 확장하기 위해 A, B, C 총 3대의 서버를 설치했다고 가정하겠습니다. 이때, 클라이언트의 요청이 들어올 때 마다 A → B → C → A … 순서대로 요청을 분산합니다. 

출처_https://hudi.blog/session-consistency-issue/

 

이런 환경에서 클라이언트의 로그인 요청이 A 서버로 전달되었습니다. 클라이언트의 세션 정보는 A서버에 생성됩니다. 그리고 직후에 해당 클라이언트의 글 작성 요청이 B 서버로 전달되었다고 합시다. 하지만 B 서버에는 클라이언트의 세션 정보가 존재하지 않습니다. 따라서 유저의 요청이 제대로 처리되지 않을 것입니다. 이런 문제를 세션 불일치 문제라고 합니다. 이런 세션 불일치 문제를 해결하는 3가지 방법이 존재합니다.

* Sticky Session
* Session Clustering
* In-Memory DB

 

# Sticky Session

출처_https://hudi.blog/session-consistency-issue/

 

Sticky Session 방식은 클라이언트의 요청이 항상 해당 클라이언트의 세션이 저장된 서버로 향하는 방식을 말합니다. 먼저 세션 정보가 없는 클라이언트가 요청을 한 경우 로드 밸런서의 기본 알고리즘대로 요청을 전달합니다. 이때 이 요청으로 인해 세션이 생성된 경우 해당 클라이언트의 요청은 해당 서버로 고정됩니다. 요청을 특정 서버로 고정시키는 방법은 쿠키를 통해 판단하거나, 클라이언트의 IP를 확인하여 판단하는 방법이 있습니다. 이 방식은 단순하지만 크게 두 가지 문제점을 가지고 있습니다.

  1. 특정 서버에 트래픽이 집중될 위험성을 가지고 있습니다. 로드밸런서는 여러 서버에 요청을 적절히 분산해서 부하가 특정 서버에 몰리지 않기 위해 사용합니다. 하지만 Sticky Session으로 인해 한 서버에 부하가 몰리면 로드밸런싱의 원래 목적을 달성할 수가 없습니다.
  2. 하나의 서버에 장애가 발생하면, 해당 서버가 갖고 있던 세션 정보가 모두 유실되어 해당 서버에 고정된 클라이언트는 다시 로그인해야 하는 문제점을 가지고 있습니다. 즉, 가용성 문제를 가지고 있습니다.

 

로드 밸런서

: 로드 밸런서는 클라이언트의 요청을 여러 서버에 분산시켜 서버에 가해지는 부하(로드)를 분산(밸런싱)시켜주는 장치나 소프트웨어를 통칭합니다. 로드 밸런싱 알고리즘은 크게 두 가지 범주로 나뉩니다.

  • 정적 로드 밸런싱
    : 정적 로드 밸런싱 알고리즘은 고정된 규칙을 따르며 현재 서버 상태와 무관합니다. 다음은 정적 로드 밸런싱의 예시입니다.
    1. 라운드 로빈 방식
      : 서버에는 클라이언트에게 요청을 전송할 위치를 알려주는 IP 주소가 있습니다. IP 주소는 기억하기 어려운 긴 숫자입니다. 이를 쉽게 하기 위해 도메인 이름 시스템은 웹 사이트 이름을 서버에 매핑합니다. 브라우저에 aws.amazon.com을 입력하면 먼저 요청이 당사의 이름 서버로 전달되고 이름 서버는 IP 주소를 브라우저로 반환합니다. 라운드 로빈 방식에서는 권한 있는 이름 서버가 특수 하드웨어나 소프트웨어 대신 로드 밸런싱을 수행합니다. 이름 서버는 서버 팜에 있는 여러 서버의 IP 주소를 차례대로 또는 라운드 로빈 방식으로 반환합니다.
    2. 가중 기반 라운드 로빈 방식
      : 가중치 기반 라운드 로빈 로드 밸런싱에서는 우선순위 또는 용량에 따라 각 서버에 서로 다른 가중치를 할당할 수 있습니다. 가중치가 높은 서버는 이름 서버에서 들어오는 애플리케이션 트래픽을 더 많이 수신합니다.
    3. IP 해시 방식
      : IP 해시 방법에서 로드 밸런서는 클라이언트 IP 주소에 대해 해싱이라고 하는 수학적 계산을 수행합니다. 클라이언트 IP 주소를 숫자로 변환한 다음 개별 서버에 매핑합니다.
  • 동적 로드 밸런싱
    : 동적 로드 밸런싱 알고리즘은 트래픽을 배포하기 전에 서버의 현재 상태를 검사합니다. 다음은 동적 로드 밸런싱 알고리즘의 예시입니다.
    1. 최소 연결 방법
      : 연결은 클라이언트와 서버 간의 개방형 통신 채널입니다. 클라이언트는 서버에 첫 번째 요청을 전송할 때 서로 활성 연결을 인증하고 설정합니다. 최소 연결 방법에서 로드 밸런서는 활성 연결이 가장 적은 서버를 확인하고 해당 서버로 트래픽을 전송합니다. 이 방법에서는 모든 연결에 모든 서버에 대해 동일한 처리 능력이 필요하다고 가정합니다.
    2. 가중치 기반 최소 연결 방법
      : 가중치 기반 최소 연결 알고리즘은 일부 서버가 다른 서버보다 더 많은 활성 연결을 처리할 수 있다고 가정합니다. 따라서 각 서버에 다른 가중치 또는 용량을 할당할 수 있으며 로드 밸런서는 용량별 연결이 가장 적은 서버로 새 클라이언트 요청을 전송합니다.
    3. 최소 응답 시간 방법
      : 응답 시간은 서버가 들어오는 요청을 처리하고 응답을 전송하는 데 걸리는 총 시간입니다. 최소 응답 시간 방법은 서버 응답 시간과 활성 연결을 결합하여 최상의 서버를 결정합니다. 로드 밸런서는 이 알고리즘을 사용하여 모든 사용자에게 더 빠른 서비스를 보장합니다.
    4. 리소스 기반 방법
      : 리소스 기반 방법에서 로드 밸런서는 현재 서버 부하를 분석하여 트래픽을 배포합니다. 에이전트라고 하는 특수 소프트웨어는 각 서버에서 실행되며 컴퓨팅 용량 및 메모리와 같은 서버 리소스의 사용량을 계산합니다. 그런 다음 로드 밸런서는 해당 서버에 트래픽을 배포하기 전에 에이전트에 충분한 여유 리소스가 있는지 확인합니다.

 

 

# Session Clustering

출처_https://hudi.blog/session-consistency-issue/

 

Session Clustering 방식은 특정 서버에서 세션이 생성될 때 다른 서버로 세션을 전파하여 복제하는 방식으로 세션 불일치 이슈를 해결합니다. 이런 방식으로 Sticky Session 방식에서 발생한 한 서버에 부하가 몰리는 문제와, 가용성 문제를 해결할 수 있습니다. 하지만, 대규모 클러스터에서는 Session Clustering 방식도 많은 문제점을 가지고 있습니다.

  1. 모든 서버가 세션을 복제하여 갖고있기 때문에 비효율적인 메모리 관리가 이루어집니다.
  2. 세션을 생성할 때 마다 데이터를 전파하고 복제하는 과정에서 Sticky Session 방식에 비해 많은 네트워크 트래픽을 사용한다는 문제점입니다.
  3. 세션을 전파하고 복제하는 과정에서 시간차로 인하여 세션 불일치 이슈가 발생할 위험성이 존재합니다. 예를 들어 A서버에서 생성된 세션이 B서버로는 전파 되었지만, 아직 C서버로 전파가 되지 않은 찰나에 클라이언트가 C서버로 요청을 보내는 상황입니다.

 

# In-Memory DB

출처_https://hudi.blog/session-consistency-issue/

 

마지막 방식은 세션 스토리지를 외부 서버로 분리하는 방식입니다. 이때 외부 세션 스토리지 서버는 일반적인 Disk-Based DB(Mysql, PostgreSQL, MongoDB 등)를 사용할수도 있지만, 입출력이 잦은 세션 특성 상 I/O 성능이 느린 데이터베이스는 사용하기 적절하지 않습니다. 따라서 세션을 저장하는 저장소로는 In-Memory DB 를 사용하는 것이 일반적입니다. 세션 데이터는 Key-Value 로 구성되어 있기 때문에 In-Memory DB 중에서도 대표적인 Key-Value DB인 Redis와 Memcached를 사용합니다.

In-Memory DB 방식은 모든 데이터를 메모리(RAM)에 저장하고 처리하기 때문에 디스크에 저장하는 전통적인 데이터베이스보다 빠릅니다. Disk-Based DB는 데이터의 영속성을 위해 사용하지만, 세션 정보는 상황에 따라 영속성을 보장할 필요가 없기때문에 휘발성 메모리인 RAM을 사용하는 것입니다. 만약  In-Memory DB 방식에서 비휘발성 데이터를 처리해야 하는 경우에는 디스크에 데이터를 저장하는 옵션을 제공하는 Redis를 통해 기능을 보완할 수 있습니다. 

세션 스토리지 분리 방식의 단점은 바로 하나뿐인 세션 스토리지에 장애가 발생하면, 모든 서버가 세션 데이터를 정상적으로 사용할 수 없게 된다는 것입니다. 이 문제는 세션 스토리지를 여러개로 구성하고, Session Clustering을 제한적으로 적용하는 방식(ex) 서버 몇 대에만 복제)으로 해결할 수 있습니다.

세션 스토리지를 분리하면 Sticky Session의 문제인 부하 집중 현상과 가용성 문제를 해결할 수 있습니다. 또한 Session Clustering의 비효율적인 메모리 관리 문제, 네트워크 트래픽 증가 문제, 시간차로 인한 세션 불일치 문제도 모두 해결됩니다.

 

 

서버 간 세션 불일치 문제를 해결하기 위한 방법을 이해하면서, 트래픽 및 서버 메모리 관리의 중요성을 또 한번 체감했습니다. 더불어 로드 밸런싱 알고리즘을 통해 트래픽 제어 기술에 대해 깊이 알게 됐습니다. 오늘 배운 3개의 해결 방법들을 적절하게 활용하여 대용량 트래픽 환경에서도 원활한 서비스를 제공할 수 있는 어플리케이션 개발을 연구해야겠습니다.