Project Load(Cloud Enginner, Devops, SRE)

    

Project Load(Cloud Enginner, Devops, SRE)

  • 소프트웨어 개발과정 수립
  • 클라우드 기반 아키텍처 설계
  • 개발과 Infrastructure as Code
  • CI/CD
  • 모니터링 및 개선

“요구사항을 기반으로 성능 목표의 정의부터 클라우드 디자인 설계, 구현, 운영단계에서 모니터링 및 개선까지의 전 과정을 경험해보고 싶다.”    

    

이 프로젝트를 시작하게 된 이유


    

이 트래픽이란 녀석은 사람으로 치면 혈액과도 같다고 생각한다. 사람의 혈액에 문제가 생기면 어느 곳에서나 병이 생길 수 있는 것처럼 이 트래픽이란 것은 시스템 어느 곳에서나 장애를 일으킨다.

그렇다면 의사가 혈액을 잘 알아야 하듯, 본디 개발자와 엔지니어 또는 이 직업을 꿈꾼다면 트래픽에 관해 다음 사항들을 알아야 하지 않을까?

  • 어떻게 원활히 흐르도록 디자인을 설계하는가
  • 그런 디자인은 구현해보는 것
  • 어디서 문제를 일으키는가
  • 어디를 어떻게 분석하는가

생각만 해도 멋진 일이다. 많은 걸 배울 것이라는 큰 기대감을 안고 시작하게 되었다. 베리 두근두근쓰

    

소프트웨어 개발과정


                      " 소프트웨어 개발과정 수립 "

    

해당 프로젝트는 분석 → 디자인 → 개발 → 최종테스트 → 운영 단계를 수립하고 나서 진행한다. 사실 이번 프로젝트는 팀원을 모집하기 전, 요구사항과 구현사항, 문제상황 등 프로젝트에 필요한 부분을 생각하여 작성을 미리 해놨었다. 팀원을 모집 후 첫 미팅을 하고 나서는 아무래도 우리 팀원분들의 프로젝트 이해가 최우선이라고 생각했다. 미팅을 하면서 모두가 한 방향을 바라보아야 원활히 진행될 것 같은 느낌이 팍팍 들어서다. 앞으로 팀원들과 어떤 task를 수행하게 될지 아직은 정해지지 않았지만 이 개발과정 수립한 내용이 전체적인 이해에 도움이 될 거라 생각했다. 그래서 열심히 작성하고 팀원들에게 설명해 볼 예정이다.

    

하지만 실제 프로젝트 진행은 스프린트 단위로 분석/설계/개발/테스트 진행, 주기적인 회의를 통한 스크럼 그리고 필요하다면 요구사항 추가까지 Agile의 요소들이 녹아있는 프로젝트를 진행할 예정이다. 칸반보드를 적극 활용할거다. 결국엔 애자일이 빠르고 익숙하다는 생각이다. 이것도 이번 주에 만나면 어필해봐야겠다.

    

    

분석 단계

초기 요구 사항을 분석하고 시스템을 기획하는 단계에는 성능에 대한 목표를 정해야 한다. 목표 응답시간, 시스템을 사용할 총 사용자수, 동시접속자 수 등 여러 Metric을 모니터링하기 위한 성능 목표를 정의해야 한다.

    

Peak Test로 결정

traffic-1

    

성능테스트에는 여러 종류가 있다.

부하 테스트 (Load Test) — 특정한 부하를 제한된 시간을 두어서 웹 어플리케이션에 이상이 없는지 파악하는 테스트

지속성 테스트 (Endurance Test) — Load Test와 유사하나 오랜 기간 부하를 줘서 하는 테스트.

스트레스 테스트 (Stress Test) — 부하의 임계점을 찾기 위해 점진적으로 부하를 올리면서 진행하는 테스트

최고 부하 테스트 (Peak Test) — 일순간 감당할 수 없을 만큼 부하를 주고, 웹 어플리케이션이 죽지 않고 제대로 동작하고 회복하는지 보는 테스트. 수강신청이나 이벤트 등 대규모 상황을 대비하기 위해 진행

    

그 외 볼륨테스트, 스파이크 테스트..

                 “ 여차저차 Peak Test로 진행 결정 !! 왜냐하면.. ”

    

프로젝트를 시작하며 본인은 트래픽이란 존재를 골똘히 생각해봤을 때 평범한 사용자들이 트래픽이란 존재를 가장 의식하게 되는 순간은 특정 day 또는 time의 이벤트로 인해 Traffic Peak현상이 발생했을 때라는 생각이 들었다. 사용자들의 불만 소리가 가장 큰 순간 아닌가? 대체 왜 서비스를 제공하는 회사들이 이런 Peak현상으로 인한 시스템 장애 현상이 주기적으로 발생함에도 불구하고 문제가 해결되지 않는 건지 궁금증을 참아볼 수 없다. 한번 해보자.

                      “ 블랙프라이데이가 떠올랐다. ”

    

성능 모델

성능에 대한 목표뿐만 아니라, 성능 모델 또한 정의해야 한다.

이는 시스템에 어떤 패턴으로 부하가 들어오는지를 정의해야 한다는 의미다.

예를 들어 어느 웹사이트에 사용자가 들어와서 페이지 컨텐츠를 1~3분 이내에 읽고 다른 페이지로 이동, 30분 후에 로그아웃한다면 한 사용자의 체류 시간은 30분, 총평균 30페이지를 보는 트랜잭션을 발생시키고 나간다고 할 수 있다.

진행하는 Peak Traffic test 프로젝트는 서비스 중인 회사에 소속되어 있거나 외주를 받은 것이 아니라 사적으로 진행된다. 따라서 애당초 어떤 비즈니스모델과 요구사항을 가지고 있지 않다. 그래서 성능모델 정의를 하기 위해서는 가정이 필요했다. 최근 블랙프라이데이가 있었지 않은가?! 블랙프라이데이의 저녁 시간대에 단발성으로 사용자가 급격히 몰리는 것을 가정했다! (추가로 전 세계 곳곳에 서비스하는 시스템이면 24시간 거의 다 걸리기 때문에 대한민국으로 한정했다.)

    

    

시스템 용량 산정 (Capacity Planning)

 “ 성능이란 용어와 함께 시스템의 목표 용량 산정방법에 대해서 알아야 한다. ”

시스템 용량 산정을 위해 사용자 시나리오를 기반으로 가정이 들어갔다. 여기서부터는 허락된 통장잔고를 적절히 감안해야 했다. 나는 돈이 없다. 마음 같아서는 누군가가 나에게 제한 없는 리소스를 제공해준다면 한번 멋들어지게 1000만명 동시접속까지 처리해보고 싶다.

    

성능관련 용어정리

먼저 성능관련 용어부터 정리해보자.

  • 응답시간(Response Time) → Request Network Time + Transaction Time + Response Network Time을 의미

  • 동시 사용자(Concurrent User) → 웹사이트를 사용하기 위해서, 현재 브라우저를 열어놓고 웹사이트를 보고 있는 것과 같이 현재 시스템을 사용하고 있는 사용자 수를 의미

  • 액티브 사용자(Active User) → 클릭을 발생시켜서 그 시간 당시에 서버에 트랜잭션을 발생 시키는 사용자

  • 트랜잭션(Transaction) → 사용자로부터의 요청을 다루는 단위

  • TPS(Transaction Per Second) → 초당 처리할 수 있는 트랜잭션의 양을 정의 한다. 주로 서버의 성능 평가 기준이 된다.

  • HPS(Hit Per Second) → 시스템이 처리할 수 있는 모든 웹 request의 초당 처리량이다. TPS가 비지니스 트랜잭션에 대한 처리 시간만을 정의 한다면, HPS는 리소스 (이미지, 자바스크립트)에 대한 request 처리량을 포함하기 때문에, TPS에 비해서 10~20 배 정도 높게 나온다

  • Peak Time →서버가 순간적으로 가장 부하를 많이 받는 순간을 정의 한다.

    

이 공식은 어디까지나 이론적인 공식이다. Network Latency 값은 가변적이며, Think Time 또한 유동적이다. 그러나 용량 산정에는 어느 정도의 산정 기준이 필요하기 때문에, 이 공식을 사용하면 대략적인 시스템에 대한 요구 용량을 예측할 수 있다.

내 프로젝트의 경우,

< 성능 목표 >

응답시간(Response Time) — 2초 이내

동시 사용자(Concurrent User) — 30,000

Think Time — 20~30초(가변적)

액티브 사용자(Active User) — 대략 1875 ~2730

TPS — 대략 938 ~1365

    

    

구현사항

  • 클라이언트 서버는 반품조회 API를 호출하여 반품 주문을 수집한다.
  • 클라이언트 서버는 최종적으로 수거완료된 주문의 결과 데이터를 송신한다.
  • 고객과 클라이언트서버는 배송조회 API를 호출하여 수신된 송장번호를 기준으로 배송 상황을 추적한다.

    

성능 목표와 모델의 정의

성능 목표와 모델을 정의하기 위해서는 먼저 주요 업무 패턴, 튜닝의 대상이 되는 시나리오에 대한 개별 성능 목표를 정의해야 한다. AWS는 너무 비싸다.. 아키텍처 패턴에 따라 다르겠지만 비용때문에 아키텍처를 변경하거나 밑의 목표들을 작은 수치부터 테스트해가며 수정해야 할지도 모른다.

< 성능 모델 >

이 서비스의 주요 사용자 시나리오는

  • 로그인
  • 반품 신청
  • 반품 조회
  • 로그 아웃

등이 된다.

이 중에서 한 사용자가 실행하는 비율을 따져봤다. 사용자가 로그인한 후, 반품 신청 1번 , 반품 조회를 1번, 로그아웃을 1번하므로 전체 트랜잭션의 횟수는 1+1+1+1 = 4회 가 된다.

성능 모델 : 로그인 25% 반품 신청 25% 반품 조회 25% 로그아웃 25% 이 비율을 기준삼아 전체 시나리오를 함께 돌리는 부하 테스트를 진행했을 때, 대략 1300TPS가 나와야 하고, 개별 시나리오에 대해서 로그인은 5%인 75TPS, 반품 신청 및 반품조회는 750TPS를 상회해야 한다. 상황이 완전 반품대란이다. 미움받는 기업?

    

    

디자인 단계

디자인 단계는 기본적으로 목표 성능과 용량을 달성할 수 있는 규모로 시스템 설계를 진행해야 한다.

Peak Time에 알맞은 맞춤형 디자인이 필요하고, 최대 성능을 기반으로 전체 시스템이 받아낼 수 있는 용량과 응답 시간을 고려해야 한다.

특히 성능과 용량은 애플리케이션 디자인뿐만 아니라, 어떤 하드웨어를 사용할 것인지, 어떤 미들웨어나 프레임워크를 사용할 것인지에 따라 용량과 성능의 차이가 크게 발생하기 때문에, 디자인 단계에서부터 성능과 용량을 감안해서 시스템을 설계해야 한다.

초기 아키텍처 설계 과정에서 궁금한 점이 많다.

  • Domain Driven Design

  • 수직적확장 vs 수평적확장

  • VM vs 컨테이너 vs 서버리스 이 셋 중 무엇을 사용해야,,

  • NLB+ ALB vs Cloudfront+ALB 무엇을 사용해야,,

  • 디도스대비: AWS WAF vs AWS shield vs CloudFlare 무엇을 사용해야,,

  • Bastion host vs Session Manager 뭘로..?

  • Batch vs lambda 스케쥴러는 어떻게?

등등 너무나 머리가 복잡하다!!

이에 관한 나의 고충은 다음에 자세히 포스팅해보겠다.

    

    

미들웨어나 프레임워크 관점에서도 정의된 성능 모델에 따라 적절한 제품군과  설계 구조를 채택해야 한다. 100,000 사용자 정도의 시스템 규모에서는 RDBMS를 사용해도 성능이나 용량상에 문제가 없다. 그러나 50,000,000 사용자 정도를 지원해야 하는 시스템의 경우 그냥 RDBMS를 사용할 수 없다. Sharding이나, NoSQL과 같은 다른 차원의 접근이 필요하다. 또한 빠른 응답 시간을 요구하는 경우 Redis나 Memcached와 같은 Cache 솔루션을 적극적으로 활용할 수 있다.

    

    

개발 단계

개발 단계는 아키텍처와 관련된 부분, 하이리스크 부분, 핵심기능, 난이도가 높은 부분 등을 개발 초기 스프린트에서 개발한다.

초기 스프린트가 끝나고 릴리즈가 되어서 성능 테스트가 가능한 QA나 스테이징 환경에 시스템이 구현되면 시스템의 아키텍처와 모듈들이 성능 목표를 달성할 수 있는지 지속적으로 테스트하고 튜닝을 수행한다.

초기 단계에 성능 목표의 달성 가능 여부가 판단되어야, 아키텍처 변경이 가능하고, 주요 성능 이슈들을 초반에 발견해야, 발견된 성능 문제들에 대해서는 같은 문제가 발생하지 않도록 디자인 가이드나 코딩 가이드를 개발자들에게 배포하여 성능에 대한 위험도를 줄일 수 있다.

    

    

최종 테스트 단계

앞의 단계에서 성능과 용량을 고려해서 설계가 되었고, 개발 초기 단계에서 성능과 용량 부분을 검증을 제대로 하였다면, 최종 테스트 단계에서는 개발된 최종 시스템에 대한 성능과 용량 부분의 측정과 미세 튜닝 (애플리케이션의 병목을 찾아서 부분적으로 수정하거나, 하드웨어나 미들웨어의 Configuration 하는 수준)을 하는 정도로 마무리가 되어야 한다. 보통 20% 내외 정도 성능이 올라간다고 보면 된다.

    

    

운영 단계

마지막으로 시스템이 운영 단계로 넘어가게 되면, 테스트시에 발견되지 않은 성능적인 문제가 있을 수 있기 때문에, 모니터링 도구를 사용하여 지속적으로 성능을 모니터링 하고, 성능상에 문제가 있는 부분을 지속적으로 수정해야 한다.

더불어 용량 부분에 대해서도 운영단에서는 고민을 해야 하는데, 일반적으로 PEAK Time의 시스템 용량이 (CPU) 80% 정도에 다다르면, 시스템 용량 증설을 고려해야 한다.

업무에 특성에 맞게 미리미리 용량을 준비해 놓는게 좋다.

마지막으로, 운영 단계에서 Performance Engineering 관점으로 챙겨야 하는 부분은 운영 로그의 수집이다. 성능 및 용량 목표 설정은 매우 중요한 과정이다. 특히 용량 목표의 경우에는 기존의 업무 시스템의 사용 패턴을 분석 하는 것이 가장 효율적이기 때문에 운영 시스템의 로그를 수집하고 분석하여 운영 중인 업무 시스템의 성능 모델을 분석 및 보유 해놓는 것이 좋다.

    

    

모니터링 Metric 구성

애플리케이션 관점

  • Response Time ㅡ Request 별 응답 시간
  • TPS ㅡ 초당 요청(Request) 처리량
  • response time

미들웨어 관점

  • Network out bound bandwidth
  • application server의 경우에는 Thread의 수와 Queue의 길이
  • DB의 경우 slow query

인프라 관점

  • CPU
  • Memory
  • Network IO
  • Disk IO
  • access log
  • cache hit rate
  • Origin Latency
  • Error Rate by status code

등등

    

튜닝(개선)


  • 문제의 정의 → 성능 개선의 가장 기본은 문제 자체를 제대로 정의 하는 것이다. “그냥 느려요”가 아니라, “성능 목표가 350TPS에 1초내의 응답 시간인데, 현재 60 TPS에 5초의 응답 시간에 WAS의 CPU 점유율이 100% 입니다.”와 같이 명확해야 하며, 문제점이 재현 가능해야 한다.
  • Break down → 다음으로는 문제가 발생하는 부분이 어떤 부분인지를 판단해야 한다. 시스템은 앞단의 로드밸런서나 미들웨어, 데이타 베이스와 같은 여러 구간에서 발생을 한다. 그렇기 때문에, 성능 저하의 원인이 정확하게 어느 부분인지를 인지하려면, 먼저 성능 시나리오가 어떤 어떤 컴포넌트를 거치는지를 명확하게 할 필요가 있다. 이 과정을 break down이라고 한다. 이 과정을 통해서 전체 성능 구간중, 어느 구간이 문제를 발생 하는지를 정의한다.
  • Isolate → 다음으로는 다른 요인들을 막기 위해서, 문제가 되는 구간을 다른 요인으로 부터 분리 (고립) 시킨다.
  • Narrow down → 문제를 isolation을 시켰으면, 근본적인 문제를 찾기 위해서 문제의 원인을 파 내려간다. Profiling을 하거나, 코드에 디버그 정보를 걸어서 문제의 원인을 분석하는 과정을 narrow down이라고 한다.
  • Bottleneck 발견 → Narrow down을 해서 문제의 원인을 계속 파해쳐 나가면 병목의 원인이 되는 근본적인 문제가 판별이 된다.
  • 해결 → 일단 병목의 원인을 찾으면 해결을 해야 하는데, 찾았다고 모두 해결이 되는건 아니다. 데이터 베이스 index를 걸지 않아서 index를 걸어주면 되는 간단한 문제도 있을 수 있지만, 근본적인 솔루션 특성이나 설계상의 오류로 인해서 문제가 발생하는 경우도 있다. 하드웨어를 늘려서 해결하는 방법도 있지만, 비지니스 시나리오 자체를 바꾸거나 UX 관점에서 해결 하는 방법도 고려할 수 있다. 예를 들어 로그인 화면이 넘어가는데 시간이 많이 걸린다고 했을때, 이 문제가 근본적으로 솔루션의 특성이라면 애플리케이션이나 솔루션 수정으로는 해결이 불가능하다. 이런 경우에는 모래 시계 아이콘이나 progress bar등을 넣어서 UX 관점에서 사용자로 하여금 체감되는 응답 시간에 대해서 느리지 않고 몬가 진행이 되고 있다고 보여주는 형태로 접근을 해서 문제를 해결할 수도 있다.

    

한없이 모자란 역량을 가지고 있는 내가, 다소 규모가 큰 프로젝트를 중심으로 소중한 팀원들을 모집했다. 모집 당시만 해도 의기양양하게 많은 걸 배우자며 팀원들을 다독였지만, 나 역시 새로운 도전을 하기에 두려운건 사실이다. 그저 이 배가 무사히 순항하길 바랄뿐이다. 그리고 돌파할 것이다. 아무도 안볼테지만 이 배의 항해일지는 이곳에 최대한 기록할 것이다. 그것이 바로 낭만.

    

    

The only thing we know is things don’t always go the way we plan
우리가 아는 단 한가지는, 모든 건 계획대로만 흘러가지 않는다는 거야.

-라이온 킹 中-