본문 바로가기
프로젝트/끄적끄적

Scale-Up과 Scale-Out 각 장단점은 무엇일까? (Session Storage, 세션 불일치)

by 나무후추통 2022. 9. 22.

 서버 1대가 감당할 수 있는 요청은 한계가 있습니다. Tomcat의 경우 요청 1개를 1개의 스레드 풀에서 가져와 사용하는데, 기본 설정 값이 200으로 돼 있습니다.

 

 그렇다면 그 이상의 요청은 어떻게 될까요? 일단 TCP 연결이므로 Connection Timeout이 발생하기 전까지 대기할 것입니다. 하지만 요청을 전부 처리하기 전에 Timeout이 발생할 경우, 요청을 받지 못하고 연결이 종료가 될 것입니다. 이 부분은 지연이 발생하는 부분을 개선하여 문제를 해결할 수 있을 겁니다.

 

 만약 감당할 수 없는 만큼의 요청이 들어올 경우 어떻게 될까요? 예를 들어 Thread도 메모리 영역에 있습니다. 우리가 스레드 풀 크기를 늘려도 메모리 공간이 부족하면 Thread를 생성할 수 없어 요청을 처리할 수가 없습니다.

 

 이렇게 '물리적으로' 요청을 처리할 수 없다면 어떻게 해결할 수 있을까요?

 

1. Scale-Up (vertical scaling)

그림 1. 스케일 업

 아주 간단한 방법은 서버의 물리적인 성능을 올리는 것입니다. 메모리가 부족하다면 메모리 용량을 늘리고, CPU가 감당할 수 없다면 멀티코어 수, 클럭이 높은 CPU로 교체하는 것이죠. 하드웨어의 가격은 기술의 발전으로 점점 낮아지고 있습니다. 또한 클라우드 컴퓨팅 서비스를 제공하는 업체를 통해서 쉽게 성능을 올릴 수가 있습니다.

 

 하지만 이것도 한계가 있습니다. 갑자기 정전이 발생할 경우, 심각한 버그로 시스템이 중단되는 경우, 새로운 기능을 배포할 때 운영 기존 서비스를 내려야 하는 경우 등 유연하게 대처하기 힘듭니다.

 

 그렇다면 '성능을 늘리면서 유연하게 대처하는 방법은 무엇일까요?'

 

2. Scale-Out (horizontal scaling)

그림 2. 스케일 아웃

 이 방법은 장비를 1대가 아닌 여러 대로 분산하여 처리하는 방법입니다. 이 경우는 전체 트래픽 요청을 여러 서버로 분산하여 부담하기 때문에 성능 향상이 가능하며 1대 서버의 장애가 전체 장애를 발생시키지 않습니다. 

 

 클라우드 서비스에서는 사용량을 모니터링하여 자동으로 서버를 증설하는 기능도 있다고 합니다.

 

2.1 발생하는 문제 1 - (어떻게 분산할 것인가)

 그렇다면 트래픽을 어떻게 분산할까요? 이와 같은 경우는 로드 밸런싱이 필요합니다. 즉, 여러 대의 서버에게 균등하게 트래픽을 분산시킬 필요가 있습니다.

 

 로드 밸런싱 기법으로는 Round Robin, Weighted Round Robin, IP Hashing, Least Connection Method, Least Response Time Method 등 다양한 방법들이 있습니다.

 

 여기서 L4, L7 로드 밸런싱으로 다시 나뉘는데, 이를 비교하면 아래와 같습니다.

 

1. L4 로드 밸런싱

  • L4 : Layer 4(전송계층) 부하 분산
  • IP, TCP, UDP 바탕으로 로드 밸런싱

2. L7 로드 밸런싱

  • L7 : Layer 7(애플리케이션 계층) 로드 분산
  • HTTP 헤더, 쿠키 등과 같은 사용자의 요청을 기준으로 분산
  • 패킷 내용을 확인하고 분산하기 때문에 특정 URL에 따라 부하를 분산하거나 쿠키 값에 의한 세분화가 가능함

 

2.2 또 다른 문제 2 - (세션 불일치)

 트래픽 처리는 이제 해결이 되었는데 다른 문제가 발생합니다. HTTP는 무상태성(stateless) 프로토콜입니다. 즉, 사용자의 상태를 알 수 없습니다. 하지만 우리가 평소에 사용하는 서비스는 '상태'를 알고 있습니다. (예 : 로그인, 장바구니 등) 

 

 이러한 사용자의 상태를 유지하기 위해서 '쿠키', '세션', 'JWT'와 같은 방법들이 있는데 이 글에서는 프로젝트에서 선택한 '세션'에 집중하도록 하겠습니다.

 

그림 3. 세션 불일치

 Tomcat에서 세션은 '메모리'에 저장이 됩니다. 즉, 1개의 서버가 처리한 세션 '그 서버' 안에 존재합니다.

 

 만약 '로그인된 사용자가 서버 1에 저장된 세션 정보''서버 2'에게 요청할 경우 어떤 문제가 생길까요? 이는 세션 불일치로 로그인이 풀리는 상황이 발생할 겁니다. 즉, 사용자 경험에 악영향을 줄 수 있습니다. 그렇다면 이 문제를 어떻게 해결할 수 있을까요?

 

2.3 문제 해결 방법 1 - (Session Storage)

 세션 불일치를 해결하는 다양한 문제들이 있는데, 대표적으로 '세션이 저장된 서버로 요청을 전달하는 Sticky Session', '하나의 서버에 저장된 세션을 다른 서버에게 옮기는 Session Clustering', '세션 정보를 외부에 저장하는 Session Storage'가 있습니다.

 

그림 4. 세션 스토리지

 제 프로젝트에는 'Session Storage'를 선택했습니다. 그 이유는 아래와 같습니다.

 

1. Sticky Session은 세션이 저장된 서버로 요청을 보낸다. 만약 그 서버에 장애가 발생하면 해당 세션과 연결된 사용자들이 모두 영향을 받는다.

2. Session Clustering은 다른 서버에게 세션을 복사하는 과정이 필요하다. 이는 네트워크 트래픽을 증가시킨다. 또한, 1번 서버의 메모리 용량이 다른 서버에게도 영향을 준다. 예를 들어 서버 1이 1GB일 경우 다른 서버도 그 정도의 용량을 확보해야 한다. (메모리가 부족해서 클러스터링 시 문제가 발생할 수 있기 때문.)

3. Session Storage는 WAS의 장애가 발생해도 로드 밸런싱을 통해서 다른 서버로 연결된다. 다른 서버의 요청에도 대응할 수 있다. 장애 대응에 유리하다. 또한 어떤 저장소를 선택하냐에 따라 클러스터링 구성이 가능하다. (예 : Redis-clustering)

3-2. Redis는 싱글 스레드로 동작하며 원자성을 보장한다. 즉, 동시성 문제에서 자유롭다.

3-3. 메모리 기반 스토리지이기 때문에 응답 속도가 빠르다.

 

참고자료