Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

전공공부

대규모 트래픽을 다루기 위한 설계 방안 본문

Study

대규모 트래픽을 다루기 위한 설계 방안

monitor 2024. 5. 15. 23:45

서론


아래 글은 제가 가상면접 사례로 배우는 대규모 시스템 설계 기초 책을 읽고 가상의 서버에 적용하여 운영한다는 가정하에 적습니다. 따라서, 틀린 부분이 있거나 더 좋은 개선점이 있으면 댓글로 피드백 부탁드립니다.

 

본론


 

일일 몇 십억건의 트래픽을 관리하고 콘텐츠를 제공하는 서버를 구성 한다는 가정하에 아래 글을 씁니다. 만일, 우리가 만든 서버가 이미지 프로세싱을 하게 된다면 어떻게 구성 할지에 대해서 논의 해봅시다.

 

우선 웹 서버에 RDB를 두고 CDN을 두고 LB를 두고 나머지 기본적인 셋팅은 K8S Cluster로 하던 VM 서버를 사용하던지 할 겁니다.

 

거두절미하고 아래와 같이 짰다고 합시다.

 

 

각 그림에 대해서 하나씩 설명해봅시다.

 

1. REDIS (캐시 서버)


캐시 서버로 사용하며 이는 적절한 TTL을 걸어서 데이터가 지속적인 방출이 됨을 막습니다.

 

캐시 서버로 사용하게 되는 이유는 우리가 보다 싶이 단일 서버가 아닌 여러 서버를 둘때 Spring Cache와 같은 dependancy를 이용해서 inMemory Cache에 유저의 세션 정보 특히 JWT Token 정보 값을 두었다고 칩시다. 그렇다면 서버 세션 메모리에 값이 남게되고 다음 요청에 LB 타고 들어온 유저는 정보가 바뀌었기 때문에 같은 데이터를 받지 못하거나 expired 될 것입니다. 따라서, 우리는 REDIS 캐시 서버를 두고 세션 정보를 둡니다.

 

또한, 이런 캐시 서버는 분산이 꼭 필요합니다. 위와 같이 REDIS를 사용한다면 MMM/SSS과 같이 적절히 마스터 슬레이브 구조로 나누어서 자동으로 Master 이 죽을 시 다른 Slave가 Master로 격상되며 Write 처리를 할 수 있겠습니다.

 

분산이 필요한 이유는 만일, 캐시정보로 쓰는 데이터 중 세션정보 이외에도 정말로 자주 일어나는 작업에 대해서 데이터를 저장하고 캐시데이터로 제공을 할 시 REDIS가 죽으면 서버 지연이 발생하고 Single Point Of Failure (SPOF)가 일어 날 수 있습니다.

 

따라서, 캐시 서버도 적절히 부하 분산을 시켜주고 데이터 방출 정책을 세워서 관리해야 합니다.

 

2. CDN (Content Delivery Network)


CDN을 두는 이유는 간단합니다. 만일, 원본 서버를 타고 이미지 파일을 요청 받아 유저가 받기 위한 시간 대비 CDN에 저장된 캐시 이미지를 가져오는 시간이 짧기 때문입니다. 특히나 대규모 서비스를 진행한다면 이와 같은 처리가 필수적입니다.

 

그래서 보통은 TTL을 걸고 특정 시간이 종료되면 요청이 들어왔을때 원본 서버로 부터 요청을 받아 CDN에 다시 업로드가 되고 사용자는 해당 데이터를 받습니다.

 

3. Load Balancer 


소위 말하는 LB를 두고 있는 이유는 사용자 요청이 마구잡이로 들어 올 때 부하 분산을 적절히 수행하기 위해서입니다. 특히나, 단일 서버가 아닌 대규모 트래픽을 버티기 위한 ScaleOut된 서버의 경우 사용자 요청을 일일이 API 서버에 등록해서 하나씩 등록 할 수 없고 이를 LB로 단순히 묶어서 부하 분산을 진행합니다. 그리고, 1 서버가 다운 되었을 때 사용자는 이런 장애 상황을 모르고 넘길 수 있습니다. 부하분산기가 살아 있는 다른 서버로 요청을 보낼 것이니까요.

 

4. DB, 데이터 샤딩


DB의 경우에도 M/S 구조를 가지며 Master가 죽었을때 (failover가 되었을때) Slave가 Master의 read/write 역할까지 수행하고 사실상 Master가 됩니다. 따라서 나은 안전성을 보장하고 Slave의 경우 기본적으로 Read를 같이 지원하기 때문에 select 쿼리의 더 나은 성능을 보장합니다.

 

당연히 Production 레벨의 DB 설계시에는 이중화 구성이 진행이되기 때문에 이는 철칙처럼 새겨야 할 것입니다.

 

규모가 만일 어마어마하게 커진다면 데이터 샤딩을 고려해야합니다.

 

데이터 샤딩의 키 값을 적절히 선정 후 적절한 알고리즘을 통해서 Data가 한 쪽 DB로 몰리는 것을 방지하여야 합니다.

 

책에서 배운 샤딩시 고려해야 할 점은 아래와 같았습니다.

 

1) 샤딩 소진 : 할당 알고리즘으로 인해서 특정 DB에만 데이터가 쌓이는 경우입니다. 이 경우 데이터 재 샤딩이 필요합니다.

 

2) 유명인사 문제 : 인스타그램이 해당 이슈로 인해서 저스틴 비버가 업로드를 하면 인스타그램 전체 서비스가 느려지는 이슈가 있었습니다. 이때도 데이터 재 샤딩이 필요 할 수 있거나 캐시 메모리를 재구성하여 해결 할 수 있습니다. 

 

5. Message Queue


사실 MQ의 경우 현업에서 직접 사용하기 전까지는 크게 사용해야 할 의무를 못 느꼈는데 수집과 가공 서버간의 격차가 커진다면 꼭 필요하다고 생각합니다. 단순히 수집하는 서버가 3000TPS 이상 매번 수집한다고 칩시다. 하지만, 가공서버의 경우 이미지 추론을 하게 된다면 크게는 초단위 요청이 진행 될 수도 있는데 이걸 버틸 수 있을까요? 바로 연결한다면 처음 10개 정도만 처리하고 모두 Timeout Exception을 내고 아무 처리가 되지 않을 겁니다.

 

따라서, 이때 MQ를 두고 두 서버 사이의 간극을 줄여줍니다. 그래서, Processing 서버와 수집을 진행하는 서버에 MQ를 둬서 수집하는 서버는 단순히 MQ를 이용해서 발행만하고 가공서버에서는 구독처리만 하면서 적절히 처리를 할 수 있을겁니다. 

 

그럼 이때 통신은 비동기로 한 번 끊고가면 수집 서버에서는 지속적으로 MQ 통해서 보내고 가공 서버에서도 지속적으로 MQ 통해서 처리 할 수 있을 만큼만 구독한 정보를 가져 올 수 있겠죠.

 

6. 데이터 센터


통상적으로 데이터 센터를 따로 두어서 관리하여 각기 다른 국가간의 유저가 요청 딜레이 됨을 방지합니다.

 

 GeoDNS를 통해서 가까운 데이터 센터로 연결도 하고 failOver시 트래픽 우회를 적절히 수행하고 데이터 센터별로 데이터 베이스를 모두 동기화를 통해서 여러 데이터베이스를 다중화하고 데이터 센터가 failOver 되었을 때 적절히 데이터를 제공 할 수 있게 장애 상황에 대응 할 수 있게해야 한다고 합니다.

 

또한, CI/CD 툴을 통해서 각 국가별로 Test를 진행 후 빌드할 수 있도록 설계 해야 합니다.

 

각 국가별 yaml 파일을 셋팅하여 각 국가별 테스트 케이스를 돌리고 이후 빌드하는 것을 지향합니다.

 

7. BFF (Backend For Frontend)


대규모 설계 시스템의 경우 접속자들이 일반적으로 Web만 존재하지 않고 App으로도 접근을 할 수가 있을 입니다.

 

따라서, 각 API 서버를 타고 인증 인가 처리된 서비스들이 웹용 엔드포인트, 모바일용 엔드포인트로 접근하여 각 엔드포인트에 맞게끔 응답 할 수 있게 한다고 합니다.

 

클라이언트 입장에서는 정말 화면에 필요한 서비스만 받으므로 별도의 가공처리 없이 바로 사용 할 수 있습니다.

 

결론


현업 서비스에서도 써 먹을 수 있는 부분이 있어서 요즘 공부하는 건인데 배울점이 많았습니다. 두고두고 공부하기 위해서 정리하였는데 우선 MQ 적용을 해서 서비스 간 간극을 줄이고 이후 진행될 서비스를 추가 개발하여 조금 더 나은 제공 서비스를 할 수 있을 듯 합니다.