글 작성자: Key Ryung

개요

이전에 진행했던 Scale-Up을 통해서 Application Server의 Resource 부족의 재검증과 성능이 개선되는 것을 포스팅했었습니다. 마지막으로 결론은 '이제는 Scale-Out을 해야 할 때'라고 적었었습니다. 그래서 이번 포스팅을 통해 Scale-Out을 어떻게 진행했는지 보겠습니다. 

 

수평적 확장(?)

#1에서 개선하여 지속적으로 사용해온 Infra 구조도입니다. 

Scale-Up된 Infra 구조

바로 수평적 확장을 적용해보겠습니다.

수평적 확장 시 Client가 분산하여 요청을 보내는 상황

현재 Client라고 볼 수 있는 nGrinder Agent가 요청을 분산해서 보낸다면 바로 수평적 확장이 가능하겠지만 추가적인 Component나 로직이 없으므로 기본적으로 기존에 요청을 보내던 Server로 보낼 것입니다. 비슷한 개념으로 MSA(Micro-Service Architecture)에서 사용되는 Client-side Service Discovery 패턴도 있습니다. 이번에는 더 간단한 방법으로 Scale-Out을 진행했습니다.

 

Load Balancer

직역하면 부하 분산기입니다. Client에게 요청을 받아 각각의 Application Server로 전달하는 역할을 맡고 있습니다. 수평적 확장의 장점으로는 성능 향상만 있는 것이 아닙니다. Server를 다중화함으로써 Availability(가용성)을 높여 단일 실패 지점(SPOF)이 되지 않도록 합니다.

Load Balancer를 적용한 Infra(서버 모두 Database와 연결되어 있다고 가정)

Load Balancer의 역할은 2개로 요약할 수 있습니다. 첫째로 부하를 분산하고 둘째로 정상인 상태의 서버에게만 요청을 보내 가용성을 높이는 역할입니다.

 

Load Balancer로 Nginx를 선택했습니다. Software Load Balancer 중에서 고려했을 때 HTTP protocol에서는  HAProxy, Nginx가 성능이 좋은 것으로 실험결과가 나와있고 HTTPS protocol에서는 HAProxy와 Envoy가 성능이 좋았습니다. 

로드 밸런서 성능 지표 비교

성능만 보았다면 HAProxy를 고르는 것이 맞는 판단이라고 생각합니다. 하지만 현재 서비스 출시를 위해 달려가는 상황이라면 Front-End Server를 따로 두지 않고 Web Server를 Front-End Server로 둔다라는 설계를 생각하고 Load Balancer로써의 성능 지표에서 성능이 준수하고 Web Server 기능까지 수행할 수 있는 Nginx를 선택했습니다.

 

* 해당 비교 자료는 2018년도 기준으로 만약 다시 선정한다면 테스트를 통해 지표를 비교해야 된다 생각합니다.

 

현재 Load Balancer를 Application Server 앞에 배치하여 부하 분산까지는 완료했습니다. 하지만 한가지 고민이 발생합니다. 로그인은 어떻게 관리하지라는 고민입니다. A 서버를 통해 로그인을 진행하여 세션을 생성한 후 같은 유저가 보낸 요청이 B 서버로 로드 밸런서에 의해 가게 되면 세션이 없기 때문에 다시 로그인해야 되는 상황이 발생합니다.

 

세션 불일치에서 Stateless로

A 서버에 있는 세션이 B 서버에는 같은 세션이 없는 현상을 세션 불일치라고 지칭합니다. 세션 불일치 현상을 해결하기 위해서 다양한 방법들이 존재합니다. Sticky Session, Session Clustering, Session Storage의 방법이 있습니다.

 

Sticky Session은 말 그대로 Session에 의존적(Sticky)으로 세션이 있는 곳으로 요청을 보내는 것입니다. 어떻게 동작하는지 생각해 본다면 Load Balancer를 통해서 구현할 수 있다는 것을 알 수 있습니다. 방식은 간단하다고 생각되지만 Load Balancer를 추가하면서 얻게 된 부하 분산, SPOF 제거의 장점을 모두 다시 잃게 됩니다. 부하가 한 서버로 집중될 수 있고 하나의 서버가 다운된다면 갖고 있는 세션 정보를 모두 잃어버리게 되기 때문입니다.

 

Session Clustering은 세션을 모두 하나로 묶어 관리한다는 의미입니다. Tomcat과 같은 Web Application Server에서 관리하며 2개 이상일 때 사용할 수 있습니다. 하나로 묶어 관리한다는 것이 무엇을 의미할지 생각해보면 결국 하나의 서버에서 생성된 세션을 다른 서버들로 보내주는 것입니다. 그렇다면 결국 복사해서 전달해야 하므로 필연적으로 오버헤드가 발생합니다. 그리고 전달해야 되는 시간 차이를 생각해본다면 세션의 복사가 완료되기 전까지는 세션 불일치 현상이 나타날 수 있으므로 확장이 쉬운 구조와는 거리가 멀어 보입니다.

 

마지막으로 Session Storage 방식이 있습니다. Session을 독립된 중앙 집중 Storage에 저장하는 방식입니다. Session 정보를 독립적으로 관리함으로써 결국 우리의 로직이 실행되는 WAS는 세션이라는 상태(State)에 대해서 무상태성을 갖게 됩니다.  무상태로 유지됨으로써 트래픽에 따라 확장이 쉬워집니다.

 

Session Storage 선택

Session Storage의 후보로는 Redis, Memcached, Hazelcast가 있었습니다. Session의 경우 읽기, 쓰기가 모두 같은 빈도로 이루어질 것이라 예상하여 In-memory DB를 후보로 선정했습니다.  Memcached의 경우 스냅샵 기능과 복제 기능이 기본적으로 없기 때문에 적용한다면 Memcached가 Fail시 세션들이 모두 사라져 서비스에 장애를 일으키므로 SPOF가 된다고 판단해서 제외했습니다. Hazelcast의 경우 Thread가 적은 경우 Redis보다 Throughtput이 더 낮은 것을 볼 수 있고 아직 인지도가 부족해 Reference가 부족한 것을 볼 수 있었습니다.

왼쪽 - Redis 공식 비교, 오른쪽 - Hazelcast 공식 비교

* Redis와 Hazelcast 공식 페이지에 가보면 서로의 Product가 더 좋다고 주장하며 그에 대한 근거들을 상세히 서술하고 있으니 한 번쯤 보셔도 좋을 거 같습니다.

 

앞서 바라본 근거들을 통해 최종적으로 Redis를 Session Storage로 선택했습니다. 초기 구성 시 가장 기본적인 스펙의 서버로 선정하고 개선해 나갈 예정이므로 Thread가 적을 경우 성능이 더 좋은 Redis를 적용하는 것이 맞다고 판단했기 때문입니다. 그렇다면 Load Balancer와 Redis까지 모두 선정했으므로 선정된 결과를 바탕으로 Infra를 구성해보겠습니다.

 

Load Balancer, Redis를 적용하여 Scale-Out한 Infra

Session Storage vs Tomcat Session

세션 Storage 세팅 후 궁금증이 생겼습니다. Session Storage는 결국 같은 서버에 있는 것이 아니므로 통신하는 비용이 추가적으로 소모되니 당연히 기존 Tomcat을 통한 Session보다 느리겠지라는 의문이었습니다. 예상한 결과가 맞는지 간단한 테스트를 진행했습니다.

Redis 적용 후 로그인 API 테스트 결과

* 해당 실험 시 Pinpoint Server가 Down 되어 데이터를 첨부 못 했습니다.

  기존 Session 처리 Redis를 이용한 Session 처리
TPS 1378.8 1050.3

예상처럼 Redis를 사용할 경우 통신이 필요하기 때문에 기존의 세션 처리보다는 성능이 저하되는 것을 관찰할 수 있었습니다. 진행한 실험은 많은 유저들을 로그인하는 과정을 진행하는 것이므로 Database와의 통신도 필요합니다. 

 

다음 포스팅에서는 Scale-Out 한 구조를 바탕으로 테스트를 진행할 예정입니다.

 

고민을 위한 여지

  • Scale-Out 된 구조에서 SPOF가 될 수 있는 곳은 어디일까?
  • 로그인, 물품 조회, 구매 API 모두 성능이 어느 정도 향상될까?
해당 프로젝트는 네이버 클라우드를 활용하여 진행했습니다.

 

REF

https://www.loggly.com/blog/benchmarking-5-popular-load-balancers-nginx-haproxy-envoy-traefik-and-alb/

 

Benchmarking 5 Popular Load Balancers: Nginx, HAProxy, Envoy, Traefik, and ALB | Loggly

We will test five different popular load balancers, analyze their performance, and give you the tools to understand them.

www.loggly.com