멀티 서버 환경에서 Session 관리와 Session Clustering
15 Nov 2020 | 다중 서버 환경 세션 관리 세션 클러스터링 세션 인증 Web RedisIndex
- Multi Server 환경에서 Session 관리
- Sticky Session
- Session Clustering
- Session 실시간 동기화
- Session 저장소 별도 분리
- 세션 저장소로 RDB가 아닌 In-Memory를 선택하는 이유
- References
Multi Server 환경에서 Session 관리
크게 3가지 방법을 생각해 볼 수 있다.
- Sticky Session(세션 고정) - 클라이언트별로 담당 서버 지정
- Session Clustering
- Session 실시간 동기화
- Session 저장소 별도 분리
Sticky Session(고정된 세션)
- 동일한 클라이언트에서 발생한 요청은 동일한 WAS에서 처리됨을 보장 => 클라이언트별 담당 서버 지정
- Cookie에 서버ID 포함하거나 클라이언트의 IP tracking을 이용한다. 쿠키가 없으면 기존 로드밸런싱 알고리즘 기반으로 서버 선정
- 아마존의 ELB(Elastic Load Balancing)는 AWSELB라는 쿠키를 생성해서 사용자의 세션을 특정 인스턴스에 바인딩한다.
- 장점
- 구현이 간단하다
- 단점
- 한 서버에 트래픽 집중 가능
- 서버가 죽으면 해당 복제본 없는 세션 정보는 유실됨
- 가용성과 트래픽 분산 관점에서 아쉬움
각 서버가 세션을 공유해 가용성을 확보하고, 분산 환경에서 세션 불일치 문제(데이터 정합성)와 트래픽 분산 문제를 해결할 수 있는 방법이 바로 세션 클러스터링
Session Clustering
- 여러 대의 컴퓨터들이 연결되어 하나의 시스템처럼 동작하도록 만드는 것을 클러스터링이라 한다.
- WAS들은 각각 독립된 세션을 가지고 있지만, 이를 하나로 묶어 마치 동일한 세션처럼 관리한다.
Session 실시간 동기화
- 서버끼리 세션의 변경사항을 실시간으로 주고 받는 방법
- 세션 정보를 TCP Socket으로 서버끼리 공유
-
다음 내용은 톰캣9.0 기준
-
All-to-all 세션 복제
- 하나의 세션에 업데이트가 생기면 나머지 모든 세션도 업데이트
- 단점
- 모든 서버가 동일한 세션 객체를 가져야 하기 때문에 많은 메모리 필요
- 세션 저장소에 데이터가 저장될 때마다 다른 모든 서버에도 업데이트해줘야 하므로 서버 수에 비례하여 네트워크 트래픽 증가 등 성능 저하 발생
- 3개 이하의 소규모 클러스터에 적합
- Primary-Secondary 세션 복제
- Primary 서버는 Secondary(Backup) 서버에 세션 객체 전체 복제
- 이외 서버에는 Key에 해당하는 JSESSION ID만 복제
- 메모리 사용이 all-to-all보다 줄어들고, 복제 시간이 절약됨
- 4개 이상의 클러스터에 용이
- 단점
- Primary와 Secondary 서버가 아닌 다른 Proxy 서버에 세션 정보 요청할 경우 Primary 서버에 요청해서 세션 객체를 받아와야함. 성능면 아쉬움
Session 저장소 별도 분리
- 세션 정보를 외부 저장소(Redis, 별도의 세션 서버)에 두고 따로 관리
- 모든 서버가 Session 저장소를 공유
- 장점
- 서버가 추가되면 새로운 서버에 세션 서버 정보만 추가해서 연결하면 되기 때문에 기존 서버의 수정 필요 없음. 확장성 굿
- 단점
- 관리 포인트 늘어남
- 응답 속도 느리고 세션 서버가 죽으면 모든 세션이 사라져서 대형 장애가 될 수 있음.
- 이를 방지하고자 Redis 서버의 다중화 필요, Replication, 홀수개
- 스프링은 세션 클러스터링을 지원하는 Spring Session 모듈 제공, 스프링 세션과 Redis 저장소를 연동해서 사용 가능
[출처] https://brunch.co.kr/@springboot/114#comment
한 서버에 장애가 나거나, auto-scaling으로 트래픽이 줄어 서버 수가 줄어드는 중에 요청이 들어왔다. 가용성을 어떻게 확보할 수 있을까?
=> 다른 서버로 요청을 보낸다. 요청을 받은 서버는 해당 세션의 정보가 없으므로 Session 서버에서 해당 세션에 대한 정보를 fetch해 응답해준다.
[출처] https://ignite.apache.org/use-cases/caching/web-session-clustering.html
그런데 왜 Redis일까? 왜 disk가 아닌 In-Memory에 저장하는 것일까?
세션 저장소로 RDB가 아닌 In-Memory를 선택하는 이유
1. 세션 저장소는 빈번한 Read/Write가 이루어지는 곳이다. 속도가 느린 Disk 기반의 데이터베이스보다 빠른 속도로 데이터를 처리할 수 있는 In-Memory 데이터베이스가 적합하다
Disk 기반 데이터베이스는 데이터를 디스크에 저장함으로써 전원이 공급 되지 않더라도 영구적으로 보관이 가능하지만, 내부 원판(Flatter)을 회전시켜서 데이터를 읽고 쓰는 기계식 방식을 사용하기 때문에 전자식 저장매체보다 속도가 느리다. In-Memory 데이터베이스는 메모리에 데이터를 저장하고 관리하기 때문에 I/O에 대한 부담을 덜 수 있다.
하지만, In-Memory는 휘발성이라 전원 공급이 안되면 데이터 사라질텐데 괜찮나?
=> 세션에 저장하는 데이터들은 영구적으로 저장하는 데이터가 아니다.
2. 세션 저장소에 저장되는 데이터는 데이터 특성상 유실되도 다시 로그인 하면 되므로 상대적 피해가 적고, Redis는 Replication을 지원하므로 가용성 확보가 가능하다.
사용자가 로그아웃을 하면 사용자의 세션 객체는 만료된다. 로그아웃을 하지 않더라도 설정된 시간에 따라 자동 만료된다. 브라우저를 종료한 경우에도 쿠키에 저장된 세션ID가 사라지니 다시 로그인 해야 한다. 이렇게 관리되는 이유는 사용자의 데이터를 영구적으로 보관할 경우, 메모리 부족 현상이 발생할 수 있고, 세션이 지속적으로 유지된다면 세션 유출시 보안상의 위험이 있으므로 일정시간이 지나면 만료시킨다. 따라서, 세션에 저장되는 데이터가 이러한 특성을 지니기 때문에, 데이터가 소멸되어도 피해가 적다. 소멸되어도 사용자가 다시 로그인을 한다면 서비스를 재사용할 수가 있다.
Redis는 Replication 기능을 지원하므로 Master-Slave로 구성한다. Master DB에 장애 발생시 failover 기능을 통해 SlaveDB를 MasterDB로 승격시켜 서비스를 지속적으로 제공할 수 있다.
3. 세션 객체는 Key-Value 형태로 저장되므로 Key-Value 형태의 데이터베이스가 세션 저장소로 적합하다.
Key-Value 형태로 데이터를 저장하는 데이터베이스인 NoSQL은 RDB처럼 복잡한 조회 연산을 지원하지 않지만, 단일 키 처리만 지원하기 때문에 고속 읽기와 쓰기에 최적화된 경우가 많다. 세션 데이터의 경우 간단한 연산만으로 처리 가능하므로 Key-Value 형태의 데이터베이스가 세션 저장소로 적합하다.
References
https://hyuntaeknote.tistory.com/6?category=867120
https://hyuntaeknote.tistory.com/7?category=867120