Scale out 환경에서 세션 불일치 해결하기

콜드펌킨·2021년 4월 26일
0

Scale out 확장 시 주의할 점

지난 포스트에서는 프로젝트에 Scale out을 도입하기로 결정하기까지의 과정을 다뤘습니다. 이번에는 Scale out 시 만난 이슈인 서버 간 세션 불일치 문제를 해결하기 위해 고민한 내용에 대해 공유해 보려고 합니다.

Scale out 방식 도입을 결정한 후 가장 먼저 들었던 궁금증은 그럼 세션 정보는 어떻게 어디에 저장하지? 였습니다. 로그인을 세션 기반으로 구현한 상태인데, 각 서버들이 사용자의 세션 정보를 공유하지 못하면 세션 체크 로직에서 문제가 발생할 것이 분명했기 때문입니다.

구체적인 상황을 설정 해보겠습니다. Scale out을 통해 서버(WAS-1, WAS-2, WAS-3)를 총 3대를 운영하고 있는 상태에서 새로운 사용자가 WAS-1에 접속하여 세션이 생성되었습니다. 이 때 아직 WAS-2와 WAS-3은 이 유저의 세션 정보에 대해 알지 못합니다. 이런 상태에서 유저가 다시 서비스에 접속할 때 요청이 WAS-2나 WAS-3에게 할당된다면, 이 서버들은 유저의 세션 정보를 찾지 못하기 때문에 인증 처리가 되지 않습니다. 그럼 유저는 요청을 보낼 때마다 매번 인증을 위해 매번 다시 로그인을 해야하는거죠. 그렇다면 이 문제를 어떻게 해결할 수 있을까요?

Session 불일치 해결하기

1. Sticky Session

※이미지 참조 : https://www.imperva.com/learn/availability/sticky-session-persistence-and-cookies/

Sticky Session 이란?

Sticky session은 어떤 유저의 요청을 최초로 그 유저의 요청을 처리해준 서버로만 보내주는 방식입니다. 이름처럼 유저의 요청을 세션 정보를 알고있는 서버에만 딱 붙여주는 겁니다. 이 때 적절한 서버에 요청을 붙여주는 역할은 로드 밸런서가 해줘야 하기 때문에 Sticky session 방식에서 로드 밸런서는 필수입니다.
대표적으로 AWS ELB(Elastic Load Balancer)는 Sticky session을 활용한 서비스를 제공하고 있습니다.

Sticky session의 문제점

하지만 사용자의 요청을 처리할 서버가 처음 세션이 생성된 서버로 고정되어 버리기 때문에 그 서버에 트래픽이 집중되어 있어도 사용자는 다른 서버를 이용할 수 없게 된다는 문제점이 있습니다. 즉, 로드 밸런싱이 제대로 이뤄지지 않을 수 있다는 겁니다. 또, 특정 서버에 장애가 발생할 시 해당 서버에 세션 정보가 저장되어 있는 사용자들은 세션 정보를 모두 잃어버리게 된다는 문제도 있습니다.
이처럼 Sticky session에서는 사용자와 세션 정보를 갖고 있는 서버를 1:1로 매핑해주어 세션 불일치를 해결해지만, 문제가 발생하면 Scale out의 장점인 트래픽 분산과 가용성을 제대로 활용하지 못하게 되는 경우가 발생할 수 있습니다.

2. Session Clustering

※이미지 참조 : https://ignite.apache.org/use-cases/caching/web-session-clustering.html

Session Clustering 이란?

Session Clustering은 서버들을 하나의 클러스터로 묶어 관리하고, 클러스터 내의 서버들이 세션을 공유할 수 있도록 하는 방식입니다. 클러스터 내의 모든 서버들이 세션 정보를 다 같이 공유할 수 있다면 사용자는 어떤 서버에 접속하더라도 세션 정보를 찾을 수 있을 겁니다.
저는 현재 Spring Boot를 기반으로 프로젝트를 진행하고 있기 때문에 WAS로 Tomcat을 사용하고 있는데요, Tomcat에서는 어떻게 Session Clustering을 구현하고 있는지 알아보겠습니다.

Tomcat Session Clustering

Tomcat에서는 크게 두 가지 방식으로 Session Clustering을 구현하고 있습니다.

  1. All-to-All Session Replication

    하나의 세션 클러스터 내에서 데이터가 변경되면 변경된 사항이 다른 모든 서버로 복제 되는 방식으로, DeltaManager 클래스를 통해 이 방식을 제공해줍니다.
    All-to-All Session Replication 방식에서는 모든 서버가 전체 세션 데이터를 유지하고 있기 때문에 다른 서버에서 세션을 찾기 위한 추가적인 네트워트 I/O가 발생하진 않지만, 그만큼 많은 메모리가 필요하다는 단점이 있습니다. 그리고 세션을 저장할 때 서버 수 만큼 복제하고 각 서버에 전달, 저장해야하기 때문에 서버 수에 비례하여 네트워크 트래픽이 증가하게 된다는 단점도 있습니다. 이러한 문제점들 때문에 All-to-All Session Replication 방식은 클러스터 규모가 비교적 작을 때 적합한 방식입니다.

  2. Primary-Secondary Session Replication

    Primary 서버의 세션 데이터를 Secondary(Backup) 서버에만 전체 복제하여 저장하는 방식으로, BackupManager 클래스를 통해 이 방식을 제공하고 있습니다.
    All-to-All Session Replication 방식과 달리 Primary 서버와 Secondary(Backup) 서버에만 전체 세션을 복제하여 저장하되, 이외의 서버들에는 세션의 Key에 해당하는 JSESSIONID만 복제, 저장함으로써 메모리를 절약할 수 있는 방식입니다.
    하지만 Primary, Secondary 서버를 제외한 다른 서버에 세션 정보를 요청할 경우 다시 온전한 세션 정보를 얻기 위해서는 Primary, Secondary에 다시 요청을 보내야한다는 문제점이 있습니다. Primary-Secondary Session Replication 방식은 비교적 대규모 클러스터 환경에서 적합한 방식입니다.

Session Clustering의 문제점

Session Clustering의 공통적인 문제점을 좀 더 살펴보자면, Scale out을 통해 서버를 추가할 때 마다 기존에 있는 모든 서버들에 대해서도 추가 셋팅 작업을 해줘야하는 불편함이 있습니다. 또, 서버가 늘어남에 따라 세션을 저장하고 찾아오는 과정에서 추가적인 부하가 발생하기 때문에 지속적인 확장에 한계가 있다는 문제점도 있습니다.

3. Session Storage

※이미지 참조 : https://thenewstack.io/how-to-build-intelligence-into-your-session-stores/

Session Storage 란?

기존의 서버 내 세션 저장소를 이용하지 않고, 별도의 세션 저장소를 두고 서버들이 이를 공유함으로써 세션 불일치를 해결하는 방식입니다.
Session Storage를 활용할 경우 세션을 저장하고 있는 별도의 저장소가 있으면 새로운 서버를 추가하더라도 추가한 서버에만 세션 저장소 정보를 명시해주기만 하면 되기 때문에 기존 서버의 수정이 발생하지 않는다는 장점이 있습니다. 또, 한 서버에 장애가 발생하더라도 세션은 이와 독립되어 별도로 존재하기 때문에 세션을 활용한 서비스에 영향을 미치지 않는다는 장점도 있습니다. 뿐만 아니라, 세션을 저장할 때 세션을 복제해 다른 서버들에 보낼 필요가 없어 성능면에서도 유리한 방식입니다.

Session Storage의 문제점

하지만 Session Storage 역시 문제점이 존재하는데요. 세션을 저장하고 있는Session storage 자체에 장애가 발생할 경우 모든 세션을 잃을 버릴 수 있습니다. 그리고 서버에서 세션을 활용할 경우 별도의 Session storage로부터 세션을 불러와야 하기 때문에 추가적인 네트워트 I/O가 발생한다는 점도 고려해야 합니다.

프로젝트에 어떤 방식이 더 적합할까?

다시 선택을 해야할 시간입니다. 앞선 포스트에서 작성했듯 Share My Hobby 프로젝트에서는 빠르게 증가하는 트래픽에 대응하기 위해 Scale out을 도입하기로 결정했습니다.
위에서 살펴본 Session 불일치를 해결하기 위한 세가지 방식들의 장단점을 살펴본 결과, 서버 확장에 따른 리소스가 가장 적고 서버 간 데이터 정합성을 유지하기 편리하면서도 Failover 측면에서도 강점을 갖고 있는 Session Storage 방식을 선택하는 것이 가장 적합해 보여 이 방식을 선택하기로 결정했습니다.
그럼 다음 포스트에서는 Session Storage, 그 중에서도 Redis를 도입하는 과정에서 살펴본 Redis의 특징과 도입 과정에 대해 알아보겠습니다.

참고자료

프로젝트

profile
배우고 때때로 익히면 즐겁지 아니한가

0개의 댓글