이번 포스팅에서는 현재 프로젝트를 시작하면서 선택한 서버 확장 방식인 Scale Out 방식에서, 로드 밸런서를 통해 부하 분산 처리를 함에 따라 생기는 문제점 중 하나인 세션 관리에 대해 어떻게 해결할 것인지, 그리고 그와 관련된 내용들에 대해 포스팅을 통해 알아보려 합니다.
세션 관리
세션 관리(Session Management)를 왜 해야 할까요? 현재 저는 진행 중인 Goods-For-You 프로젝트에서 회원 로그인 기능을 구현하려 합니다. 회원 로그인 기능은 다음과 같은 과정으로 진행될 것으로 생각이 됩니다.(Goods-For-You 프로젝트는 대용량 트래픽을 받는 상황에서, 서버의 성능과 고가용성을 생각하면서 진행되고 있는 프로젝트입니다.)
- 사용자가 회원가입 시 입력한 아이디, 비밀번호를 입력한다
- 서버는 사용자가 입력한 아이디, 비밀번호를 확인해 일치하면 인증을 처리하고, 그렇지 않다면 일치하지 않는 사용자로 처리한다.
- 사용자는 로그인이 되어 있는 상태로 어플리케이션을 사용한다.
위 과정에서 로그인이 되어 있는 상태라는 말에 더 부가적으로 설명을 하자면, 현재 프로젝트는 웹 기반 애플리케이션이기 때문에 웹은 기본적으로 HTTP 프로토콜을 사용합니다. 또한 HTTP 프로토콜의 특징 중 하나인 Stateless 즉, 상태를 가지지 않는다는 특징이 있습니다.
하지만 로그인과 같이 상태를 저장해야 하는 경우가 생기게 됩니다. 이럴 때 상태를 관리하는 방법으로 쿠키와 세션을 사용할 수 있습니다.
그중 세션을 관리하기 위해서는 여러 방법이 존재하는데, 세션을 관리하는 여러 가지 방법에 대해 각각의 장단점에 대해 알아보고, 현재 프로젝트에서는 어떤 방식을 채택하는 것이 적합할지 생각해 보도록 하겠습니다.
Sticky Session
스티키 세션 방식은 클라이언트의 첫 요청을 받은 서버로 그 이후의 모든 요청이 가게 되는 방식입니다.
이렇게 스티키 세션 방식을 이용해, 세션을 관리하게 되면 첫 요청 이후 모든 요청을 특정 서버로 고정하기 때문에 다중 서버 환경에 따른 세션 불일치 문제를 쉽게 해결할 수 있습니다.
하지만 모든 요청을 특정 서버로 고정한다는 점 때문에, 로드 밸런싱의 장점을 이용하지 못하기 때문에 다수의 사용자의 요청이 특정 서버로 몰리게 되면 결국 특정 서버만 과부하가 오게 되어 서버는 다운되고, 서버가 다운되게 되면 해당 서버에 존재하던 세션 데이터는 유실되게 됩니다.
이러한 스티키 세션을 사용할 때의 단점 때문에 제가 현재 진행 중인 프로젝트에는 적합하지 않다고 판단했습니다.
Session Clustering
클러스터링이란 똑같은 구성의 여러 대의 서버를 병렬로 연결한 상태를 말합니다. 쉽게 말해 여러대의 컴퓨터(서버)를 마치 하나의 가상 컴퓨터처럼 업무를 수행하도록 하는 것을 의미합니다.
세션 클러스터링은 WAS(Web Application Server)가 2대 이상 연결되어 있을 경우 연결된 모든 서버의 세션을 동일한 세션으로 관리할 수 있도록 해주는 것을 의미합니다.
세션 클러스터링을 지원해 주는 WAS로 WebLogic, Jeus, Wildfly, Jboss 등이 있습니다. 그중 현재 진행 중인 프로젝트에서 사용 중인 Tomcat의 세션 클러스터링 방식에 대해 좀 더 자세히 알아보도록 하겠습니다.
톰캣 에서의 세션 클러스터링
톰캣에서 세션 복제(session replication)를 사용하려면, 다음과 같은 세 가지 방법을 사용할 수 있습니다.
- 세션 persistence를 사용하고, 세션을 공유 파일 시스템에 저장하는 방식입니다.(PersistenceManager + FileStore)
- 세션 persistence를 사용하고, 세션을 공유 데이터베이스에 저장하는 방식입니다.(PersistenceManager + JDBCStore)
- 메모리 내 복제(In-Memory-replication)를 사용하고, 톰캣과 함께 제공되는 SimpleTcpCluster를 사용하는 방식입니다(lib/catalina-tribes.jar + lib/catalina-ha.jar)
- SimpleTcpCluster에 대한 자세한 내용은(https://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/ha/tcp/SimpleTcpCluster.html) 링크에 있습니다
또한 톰캣은 Delta Manager를 사용해 세션 상태를 전체 노드에 복제를 하거나(all-to-all replication), 하나의 노드에만 백업 복제(backup replication)를 수행할 수도 있습니다.
위 그림처럼 All-to-All 방식은 하나의 세션 저장소에 변경되는 사항이 발생하면 변경 사항이 다른 모든 세션에 복제가 되는 것을 말합니다.
이러한 All-to-All 방식은 모든 저장소에 동일한 세션이 저장되어 있기 때문에 서버 하나에 장애가 발생하더라도, 장애가 발생한 서버의 세션 데이터를 유지할 수 있습니다.
하지만 all-to-all 방식은 각각의 서버가 동일한 세션 객체를 가져야 하기 때문에 많은 메모리가 필요합니다. 또한 세션 저장소에 데이터가 저장될 때마다 모든 서버에 값을 입력해서 수정사항을 복사해주어야 하므로 서버 수에 비례하여 네트워크 트래픽이 증가하게 되고 그에 따라 성능 저하가 발생하게 됩니다. 그러므로 서버 수가 적은 소규모 클러스터 방식에서 좋은 효율을 보여줍니다.
위와 같은 이유 때문에 DeltaManager는 소규모 클러스터에 적합한 방식이지만, 노드가 4개 이상인 대규모 클러스터에서는 권장하지 않는 방식입니다.
BackUpManager 방식은 Primary-Secondary 방식으로 Primary 서버의 세션 객체의 Key-Value 전체를 Secondary(BackUp) 서버에 복제합니다. 이렇게 세션이 하나의 백업노드에만 저장되는 특징 때문에 all-to-all 방식보다 메모리의 사용이 줄어들게 됩니다.
또한 세션 객체 전체(Key-Value)를 전체 세션에 복제하는 것보다 백업노드를 제외한 노드들에는 세션 객체의 Key만 복제하는 것이 네트워크 트래픽도 줄어들기 때문에 all-to-all 방식에 비해 상대적으로 시간이 절약됩니다. 이러한 이유 때문에 BackUpManager 방식은 대규모 클러스터의 경우에 적합합니다.
그렇다면 현재 진행 중인 프로젝트에서는 Tomcat에서 제공하는 Session Clustering 방식 중 BackUpManager 방식을 채택하면 될까요?
BackUpManager 방식을 채택하기에는, Primary 서버와 Secondary 서버를 제외한 Proxy 서버에 세션 정보를 요청할 경우에 다시 Primary 서버에 요청하여 해당 Key에 맞는 객체를 받아와야만 합니다. 이 경우에도 객체를 요청하고 받아오는 과정에서 발생하는 네트워크 통신 비용을 무시할 수 없다 생각했습니다.
그렇다면 스티키 세션과 세션 클러스터링 방식의 단점을 보완하여 다중 서버 방식에서 세션을 관리할 수 있는 방법인 세션 서버를 사용하는 방법을 설명하겠습니다.
Session Storage
세션 스토리지란 기존의 서버가 갖고 있는 로컬 세션 저장소를 이용하는 것이 아닌, 별도의 세션 저장소를 사용하는 것을 의미합니다.
위 그림과 같이 세션 스토리지가 분리되면, 서버가 확장되어도 각각의 서버에 세션 스토리지에 대한 정보만 입력해 주면 세션을 공유할 수 있게 됩니다.
이러한 세션 스토리지 방식을 사용한다면, 로드밸런서의 로드밸런싱 알고리즘만 잘 구현되어 있다면 Stick Session 방식처럼 한 서버에 트래픽이 집중되는 현상을 고려하지 않아도 되게 됩니다.
또한 서버 한대가 장애가 발생하더라도 별도의 세션 저장소가 존재하기 때문에 세션 정보가 유실되지 않기 때문에 서버의 고가용성을 확보할 수 있습니다.
그리고 서버 확장으로 인해 생긴 세션 불일치 문제 또한, 여러 대의 서버가 하나의 세션을 사용하기 때문에 기존에 개별적으로 갖고 있던 로컬 세션 저장소의 세션 불일치 문제가 발생하지 않습니다.
세션 저장소가 한대이기 때문에, 세션 불일치 문제 해결을 위해서 세션 클러스터링 방식처럼 별도의 세션 복제를 할 필요가 없어서, 추가적인 메모리나 네트워크 통신을 필요로 하지 않기 때문에 성능적인 문제도 해결이 가능합니다.
하지만 세션 저장소를 복제해야 할 때가 있습니다. 이는 앞서 설명한 세션 불일치 문제를 해결하기 위해서 복제를 하는 것이 아니라, 세션 저장소를 한대를 운영한다는 것은 해당 세션 저장소에 장애가 발생한다면, 모든 세션과 관련된 서비스 이용이 불가능하다는 뜻이기 때문에, 고가용성을 확보하기 위해 동일한 세션 저장소를 하나 더 복제해서 구성하는 것입니다.
이러한 세션 저장소로는 어떤 것을 쓰는 게 좋을지, 다음 포스팅에서 알아보도록 하겠습니다.
'프로그래밍 > 프로젝트' 카테고리의 다른 글
도커 컴포즈 사용 시 DB 초기화 문제 해결 과정 (0) | 2023.03.18 |
---|---|
캐싱은 언제 적용하는게 좋을까? (2) | 2023.03.07 |
CAP 이론을 바탕으로 NoSQL 을 적용 할 만한 포인트 고려 (0) | 2023.03.02 |
GoodsForYou 패키지 구조에 대한 고민(포트와 어댑터) (0) | 2023.02.25 |
인증 방식으로 세션 VS 토큰 어떤걸 선택해야 할까? (0) | 2023.01.17 |