다중 서버에서 세션 불일치 문제를 해결하는 방법
세션 불일치 문제란?
단일 서버에서 세션에 대한 요청을 처리는 문제가 되지않지만, 다중 서버 환경이라면 이야기가 다르다.
인증 정보 세션을 예시로 든다면 유저A는 A서버에서 로그인을 진행했고, 유저B는 B서버에서 로그인을 진행했을 때
아무런 설정 없이 두 대의 서버를 운영 중이라면 유저의 요청을 어떤 서버에서 받을 지 알 수 없다.
만약 유저A가 B서버에 인증 정보를 요구하는 요청을 보냈다면? B서버에는 유저A의 인증 정보가 없어서 실패 응답을 받을 것이다.
즉, 요청이 어떤 서버로 들어가냐에 따라 결과가 랜덤하다는 뜻이다.
해결 방법
Sticky Session
서버가 여러 대인 경우는 로드 밸런서에서 모든 클라이언트의 요청을 받고 요청을 서버로 넘겨주게된다.
이때 로드 밸런서에서 유저A의 요청은 A서버로만 보낸다면 A서버에는 인증 정보가 있기 때문에 문제가 해결된다.
Sticky Session은 유저의 요청을 처리하는 서버가 고정된 세션 처리 방식이다.
즉, 유저에 대한 전담 서버를 지정하는 방식이라고 생각하면 된다.
Sticky Session은 간단하게 구현할 수 있다는 장점이 있지만, 아래와 같은 문제점들을 가진다.
- 사용자가 접속하는 서버가 고정되어 있기 때문에 하나의 서버에 트래픽이 집중될 수 있다.
- 서비스 중 하나의 서버에 장애가 발생하면 그 서버에 있는 세션 정보는 모두 유실된다.
Session Clustering
서버들을 하나의 클러스터로 묶어서 클러스터 내의 서버들이 세션을 공유할 수 있도록 하는 방식
WAS 마다 세션 클러스터링 방식이 조금씩 다르다.
Tomcat Session Clustering
- All to All 방식
- 하나의 세션 클러스터 내에서 데이터가 변경되면 변경된 사항이 다른 모든 서버로 복제되는 방식으로 Tomcat의 DeltaManager 클래스를 통해 구현된다.
- 고른 부하분산이 가능하고 다른 서버에서 세션을 찾기 위한 추가 요청이 발생하지 않아서 빠르지만, 메모리를 많이 사용한다는 단점이 있다.
- 추가된 세션을 전파하는 중에 들어온 요청에 대해 불일치 문제가 발생할 수 있다.
- Primary-Secondary 방식
- Primary Server에서 모든 세션을 저장하고, Secondary Server에 백업을 한다. 이후 다른 Proxy Server에는 JSESSIONID만 복제해서 저장함으로써 메모리를 절약할 수 있다.
- 하지만 Proxy Server에 요청이 들어올 때는 세션의 값을 가져오기 위해서 Primary, Secondary에 다시 요청을 보내야한다는 문제가 있다.
세션 클러스터링은 stickey session 방식보다 트래픽 분산이 유리하다는 장점이 있다.
하지만 서버를 증설할 때마다 클러스터링 설정을 해줘야하고, 서버가 증설될 수록 메모리 관리가 힘들고 서버간 데이터 공유로 인한 네트워크 트래픽 증가 문제, 세션 전파 작업 중에 요청이 들어왔을 경우 세션 정보 불일치 문제가 발생할 수 있다는 단점이 있다.
Session Storage
위와 같은 문제들을 해결하기 위해서 Session Storage 방식이 가장 널리 사용된다.
서버에서 세션을 저장하는 것이 아닌 외부 저장소를 활용하는 방식으로 disk 보다는 memory DB에 저장해서 속도가 느려지는 것을 최대한 방지하는 것이 좋다.
별도의 세션 저장소를 공유함으로 세션 불일치 문제를 해결하고, 서버간 세션 공유를 위한 트래픽이 발생하지 않으며, 메모리 관리 또한 한 곳에서 전부 관리하기 때문에 더 안정적이다. 또한, 클러스터링 설정도 필요없다.
하지만 외부 DB의 I/O가 발생하므로 서버에서 저장된 세션을 가져오는 방식보다는 느리다.
개인적으로 요즘 하드웨어 성능을 생각했을 때 느려봤자 사용자가 느낄 수 있을 만큼 차이가 나진 않을 것 같다는 생각이다.