본문 바로가기

[Cloud]/[GCP]

[GCP] Cloud Monitoring 로 VM 인스턴스 로그 수집하기 - 2. 부하테스트(Locust)

728x90

[ 부하테스트 ]

다음은 지정한 URL로 부하테스트를 해보려고 한다. 사용할 툴은 바로 Locust! Python으로 스트립트를 작성하기도 하고, 또 사용하기 쉽다고 해서 바로 써보기로 했다. 정식 document는 다음과 같다. docs.locust.io/en/stable/

 

Locust Documentation — Locust 1.4.3 documentation

© Copyright Revision 48de4444.

docs.locust.io

[ 현재 상태 ]

현재 GCP상에 올려놓은 내 서버는 다음과 같다.

gcloud 명령어로 나타낸 각 인스턴스의 정보는 다음과 같다. 무료 인스턴스인 f1-micro가 얼마나 버틸 수 있을것인지....

 

[ 부하테스트 툴 : Locust ]

    Locust의 아이디어는 간단하다. 단어 자체가 가지는 의미는 메뚜기의 한 종류를 가리키는 것인데, 메뚜기 떼가 뛰어다니는 것 처럼 웹페이지에 부하를 주는 것을 의미한다. 분산형으로 짜여져 있으며 로드 테스트 및 시스템이 처리 할 수있는 동시 사용자 수를 파악하기위한 것 이 목적이다.

locust.io/

 

Locust - A modern load testing framework

Example code A fundamental feature of Locust is that you describe all your test in Python code. No need for clunky UIs or bloated XML, just plain code. Select example Simple With HTML parsing Nested TaskSets

locust.io

  document에서 보면, Locust 는 easy to use, scriptable and scalable performance testing tool이라고 설명되어 있다. 말 그대로 python으로 scriptable 하고, scalable하다. 무엇 보다 중요한 것은 esay to use, open-source라는 점..ㅎㅎ

설치도 간단하다.  pip으로 설치하면 끝!

pip3 install locust

 

[ Locust 테스트 파일 작성 ]

    앞서 소개했듯이, Locust는 scriptable하다. 즉 python코드로 어떤식으로 부하를 줄 것인지를 설정할 수 있다. 아래는 간단하게 작성해본 부하테스트용 파일이다. 관련 내용은 document의 Quickstart에 굉장히 자세하게 나와 있으니 참고하면 좋을 것 같다.

1. 먼저 필요한 모듈을 import 해준다.

import time
from locust import HttpUser, task, between

2. 테스트 유저 클래스를 선언해준다.

class WebsiteTestUser(HttpUser):

    이 클래스는 우리가 부하테스트를 하면서 사용하게 될 유저의 객체를 생성하는 데 사용된다. 이 클래스는 HttpUser클래스를 상속받는데, HttpUser클래스는 각 유저에게 client속성을 부여하게 된다. 따라서 각 클래스는 마치 실제 유저가 사용하듯이 http request 요청을 보낼 수 있게 된다. 

3. 다음은 시뮬레이션 상황을 구성해 준다. 아래 예시 코드에서 알 수 있듯이 task와 task사이에 유저가 기다리는 시간인 wait-time()을 줄 수도 있고, 각 유저가 시뮬레이션을 하는 상황에서 어떤 작업을 수행하는지 task를 나누어 적용할 수 도 있다. 이때 각 task는 @ notation을 이용하며, ( )안에 그 빈도수를 지정할 수 도 있다. 각 유저가 접속후 모든 task를 수행하는 것이 아니므로, 빈도수에 따라 랜덤하게 작업을 수행한다고 가정하고 시뮬레이션을 진행하는 것이다. 아래 글을 참고하면 친절하게 설명이 되어있다. 나의 경우 notification server로, noti가 오는 즉시 웹훅 엔드포인트로 이를 전달하는 것이 목적이므로, wait_time을 없애고 동작하도록 했다. host url에 이어지는 내용을 적어주고, json데이터에는 내가 보내고자 하는 json데이터를 집어넣었다.  이제 테스트를 수행해보자!

 

Quick start — Locust 1.4.3 documentation

In Locust you define your user behaviour in Python code. You then use the locust command and (optionally) its web interface to spawn and simulate a number of those users while gathering request statistics. More options To run Locust distributed across mult

docs.locust.io

import time
from locust import HttpUser, task, between

class WebsiteTestUser(HttpUser):
    #wait_time = between(0.5, 1)

    @task
    def task1(self):
        # self.client.get("/api/v1/notice")
        pass

    @task(3)
    def task2(self):
        # self.client.get("/api/v1/notice")
        # time.sleep(1)
        pass

    def on_start(self):
        self.client.post("/api/v1/notice", json={"comments_created_at": "cm2", "comments_id": "cm1", 
                                                 "posts_id": "p1", "posts_title": "p2" })

 

[ Locust 수행 ]

실행명령어는 다음과 같다. -f tag뒤에 작성한 locust file를 불러주기만 하면 끝!

locust -f locust_files/my_locust_file.py

코드를 수행하고 나면 로컬의 8089 포트를 통해 Locust의 web-UI가 다음과 같이 열리게 된다. 여기서,
Number of total users to simulate 는 동시접속자 수를, Spawn rate은 접속자 증가속도를, Host는 테스트할 url을 의미한다. 나는 요구사항이 동시접속자 1만명에, 초당 500의 request를 버텨내는 것이 목적이라 아래와 같이 설정했다.

Start swarming을 클릭하면 부하테스트가 시작된다. 
결과 1 : WaitTime(0)  접속자: 10000/증가속도: 500                 ->        커버 가능, 하지만 응답시간 극심하게 증가. 10000/1000 동일.

0

결과 2 : WaitTime(0.5~1) 접속자: 10000 / 증가속도: 500,                  WaitTime(1~2)로  접속자: 10000 / 증가속도: 500

    몇가지 경우를 시도해 봤다(참고로 시도한 vm instanse 는 gcp의 f1-micro이다). wait time이 0일때는 fail 없이 커버가 가능했으나 응답시간이 굉장히 늘어났다. 이는 각 처리를 진행하는 과정에서, wait-time이 주어지지 않아 병목현상이 발생한 것이라고 판단했다.
   또한 각 유저의 wait-time이 1~1.5초로 늘어난 경우, 유저수가 증가하는 과정에서 1%의 failure가 발생했다.이는 서버가 부하를 견디지 못한 것으로 판단했다. 더불어 유저들의 median-response-time(응답시간의 중앙값)과 95%의 응답이 처리되기 까지의 차기가 현저하게 벌저지는 현상(Dump)가 나타났다. 나는 이 현상이 마찬가지로 서버가 각 유저마다 wait을 하는 과정에서 어떤 응답은 충분한 시간이 주어졌지만 어떤 응답에서는 병목현상이 발생하면서 중앙값은 500~1000이나  95%의 응답이 처리되기까지는 시간이 한참 걸린 원인이라고 분석했다.

+ 추가) 나중가서 알게 된 사실이지만 이 병목현상은 클라우드 아키텍쳐에 의한 문제였다
buildabetterworld.tistory.com/132?category=859595

 

[GCP] Cloud Monitoring 로 VM 인스턴스 로그 수집하기 - 4. 중간 점검,앞으로 할 일 정리

[ 발생한 문제 정리 ]   1. 원래는 한창 celery에 관한 포스팅을 준비하고 있었는데 갑자기 문제가 터졌다. 여러가지 서비스를 이제 클라우드상에 배포할 예정인데 다음과 같이 Static IP에 대한 charge

buildabetterworld.tistory.com

 

    사실 notice-server 본래의 목적을 위해서라면 충분히 사용가능한 서버라고 생각한다. 예를 들어 10000명의 사용자가 접속중이고, 사용자들이 초당 request를 준다고 가정했을때, 최악의 경우 3000ms 즉, 3초 안에는 notice를 프론트 서버로 보낼 수 있다는 뜻이기 때문이다. 알람이 3초 늦는다고 불편함을 느낄 유저는 사실 거의 없을것이라 생각한다. 하지만 이미 시작해 버린 실험이라 끝을 봐야한다...

이 문제를 해결하기 위해 notice-server에는 celery를 적용시켜보고, google monitoring으로 로그를 기록해보려고 한다.

 

+ 추가) Docker와 Kubernetes를 사용하는 방법도 있다!! 이후에 추가로 적용해보고 기록해 놔야겠다
docs.locust.io/en/stable/running-locust-docker.html

 

Running Locust with Docker — Locust 1.4.3 documentation

The docker image can be used like this (assuming that the locustfile.py exists in the current working directory): Docker Compose Here’s an example Docker Compose file that could be used to start both a master node, and worker nodes: version: '3' services

docs.locust.io

 

728x90