Nginx 로드밸런싱 애플리케이션 성능 테스트+ 무중단 배포

LJH·2021년 6월 12일
2

DevOps 강의 (feat. Foo)

목록 보기
9/16

해당 내용은 Class101의 현직 대기업 개발자 푸와 함께하는 진짜 백엔드 시스템 실무! 강의를 기반으로 작성했습니다.

Artillery로 성능테스트 하는 자세한 과정은 이전 글을 참고하자!

😀 목표

  • 로드밸런싱된 CPU bound 애플리케이션 스트레스 테스트(TPS 확인)
  • 스트레스 테스트 도중 배포하여 무중단 배포가 되는지 확인

1. Artillery로 스트레스 테스트 - 인스턴스 3개

스트레스 테스트 할 때 처음에는 짧은시간, 적은 TPS(Transactions Per Second)로 시작하는게 좋다. 이후 조금씩 TPS를 올려 언제부터 버티지 못하는지 확인해봐야 한다.

서비스의 Peak 시간에 유입되는 트래픽을 버틸 수 있는 수준이 될 때 까지 테스트가 필요하다. 짧은 시간 매우 높은 트래픽을 견뎌낼 수 있는 서버 개수(혹은 저장소, 코드에서의 병목)을 찾아냈다면, 스트레스 테스트 시간을 아주 길게 테스트 해봐야 한다.

이유는 단기적으로 문제 없으나 장기적으로는 서버 자원이 고갈되고 있는 상태일 수도 있기 때문이다.

1-1. 첫 번째 테스트

  • 지난 번에 작성한 스크립트에서 target만 Nginx 인스턴스 ip로 변경해주면 된다.
  • 5분동안 초당 1회 요청을 보내는 테스트이다.

  • 360개의 모든 요청이 성공한 걸 볼 수 있다. 요청을 늘려보자

1-2. 두 번째 테스트

  • 가상 유저를 8로 변경했다. 5분동안 초당 8회 요청을 보내는 것과 같다.

  • 2499개의 요청이 성공했고 381개의 요청이 ETIMEDOUT이 났다. 타임아웃이 났다면 500 에러가 나와야하는데 왜 500 상태코드가 떨어지지 않았을까?

  • 애플리케이션 서버는 정상적으로 응답을 받을 수 있는데 Nginx가 Hang상태에 빠졌을 가능성이 높다. 애플리케이션 서버가 정상적으로 응답을 받을 수 있는 상태였음에도 불구하고, Nginx가 Hang에 빠져 지금처럼 500, 502 에러 없이 바로 ETIMEDOUT이 발생할 수 있다. Nginx가 응답이 없어졌기 때문에 500, 502 에러를 뱉지 않은 것 이다.

1-3. 세 번째 테스트

  • 가상 유저를 12로 변경했다. 5분동안 초당 12회 요청을 보내는 것과 같다.

  • 두 번째 테스트와 비슷하게 2466개의 요청이 성공했다.
  • 현재 환경에서 버틸 수 있는 TPS는 2400~ 2500 인 것 같다.

1-4. 네 번째 테스트

  • 그냥 아무것도 뜨지 않는다.. 5760개의 모든 요청이 모두 타임아웃 에러가 났다.

1-5. 500에러와 502에러 차이

  • 강의에서는 위처럼 500에러와 502에러가 나왔다.

  • 500에러는 CPU 바운드 애플리케이션이 요청에 대한 응답을 할 수 없는 상태가 되어서
    애플리케이션 자체에서 500에러가 나왔을 것 이다.

  • 502에러는 애플리케이션이 500에러를 계속 던지다가 500에러를 던질 힘조차 없으면
    애플리케이션 자체가 종료가 되는데 이를 행(Hang) 상태에 빠진다고 이야기 한다.

  • 행 상태에 빠진 애플리케이션은 더 이상 요청을 받을 수 없고 그 때 부터는 Nginx가 행 상태에 빠진 인스턴스가 더 이상 요청을 받을 수 없다고 생각을하고 연결을 끊는다. 그 이후 부터는 502에러가 떨어지는 것 이다.

결론은 현재 환경에서 3개의 애플리케이션 서버를 두고 Nginx로 로드밸런싱 했을 때의
TPS는 2400~2500 정도이다.(당연히 Nginx 인스턴스의 사양이나, 애플리케이션 인스턴스의 사양, 애플리케이션의 로직에 따라 다르다. 단순히 서버의 개수를 보고 판단해서는 안된다.)

이제는 워커 인스턴스 2개를 죽이고 하나의 인스턴스로만 스트레스 테스트를 진행해서
TPS를 확인해보자.


2. Artillery로 스트레스 테스트 - 인스턴스 1개

2-1. 컨테이너 죽이기

  • 컨테이너 정보 확인
    • docker ps 명령어로 현재 실행 중인 컨테이너 정보를 확인 할 수 있다.
    • docker ps -a 명령어는 실행중이지 않는 모든 컨테이너까지 볼 수 있다.
  • 컨테이너 죽이기
docker container kill -s 15 [Container Id]
  • 여기서 -s 15는 컨테이너가 스스로 Graceful하게 종료하도록 한다.

  • Graceful 종료라는 것은 애플리케이션이 스스로 실행중인 로직을 전부 다 처리한 다음에 종료하도록 해준다.

  • 이후 인스턴스 2,3 에 접근해보면 접근이 안되는걸 확인할 수 있다.

2-2. 스트레스 테스트

  • 초당 요청을 4개로만 해도 벌써 타임아웃 에러가 난다.
  • 150초쯤 지나자 모든 레이턴시가 커지면서 모든 요청이 타임아웃 나기 시작한다.

지금까지 인스턴스 1개일 때와 3개일 때와 성능을 비교해보았다.
이젠 무중단 배포를 테스트 해보자.


3. 무중단 배포 테스트

  • 3개의 인스턴스를 모두 동작시키고 Artillery를 동작시키고 하나의 인스턴스씩 죽여보면서
    문제없이 요청이 처리되는지 확인해보면 된다.
  1. 스크립트를 실행시킨다.(사용자들로부터 요청이 들어온다)

  2. 1번, 2번 인스턴스의 컨테이너를 죽인다.(1번, 2번 인스턴스에 새로운 버전을 배포한다.)

  3. 1번, 2번 인스턴에 젠킨스를 통해 다시 빌드한다.(새로운 버전 배포가 끝나고 애플리케이션 서버를 다시 동작시킨다.)

  4. 테스트 결과를 보고 모든 요청이 처리됬다면 무중단 배포에 성공이다.

  • 테스트 하기전에 이전에 죽인 컨테이너를 docker start 명령어로 다시 실행시킨다.
docker start [Container Id]
  • 또는 젠킨스로 빌드해서 다시 배포해줘도 된다.

3-1. 스크립트 실행

  • 하나의 인스턴스만 살려둘 거기 때문에 가상 유저를 1로 변경하고(스트레스를 낮) 스크립트를 실행한다.

3-2. 컨테이너를 죽인다 (새로운 버전 배포)

  • 스크립트를 실행 시키고 1번, 2번 인스턴스는 컨테이너를 죽인다.

3-3. 젠킨스를 통해 다시 빌드 (배포 완료 후 서버 다시 동작)

  • 젠킨스에서 다시 빌드해서 1번과 2번 인스턴스를 살려준다.

3-4. 결과 확인

  • 모든 요청이 정상적으로 처리된 걸 확인 할 수 있다. 100초 구간쯤 레이턴시가 튀는 부분이 있는데 아마 1번,2번 인스턴스를 죽인 시점일 것이다.

  • 성공적으로 무중단 배포가 이루어 졌다.


4. 지금까지 진행했던 내용 정리

  1. JDK 설치 , GCP 인스턴스생성, Docker Desktop 설치

  2. CPU를 극단적으로 사용하는 애플리케이션 만들고 GCP 인스턴스에 도커라이징 하여 배포

  3. Artillery 툴로 스트레스 테스트 해보기

  4. 젠킨스 세팅 후 배포 자동화

  5. Nginx를 통한 로드 밸런싱 환경 구성 후 스트레스 테스트 해보기

  6. 무중단 배포 테스트

굉장히 다양하고 어려운 것들을 쉽고 알차게 배웠다..
앞으로는 Git, I/O바운드 애플리케이션, Message Queue, ES 를 배운다!

0개의 댓글