Artillery로 스트레스 테스트 하기

0

Artillery로 부하 테스트를 해보자.

ArtilleryVisit Website는 Node.js로 작성된 스트레스 테스트 도구이다.


$ npm i -g artillery

artillery를 먼저 설치해 주자.


{
  "config": {
    "target": "http://localhost:3000",
    "phases": [
      {
        "duration": 60,
        "arrivalRate": 5
      }
    ],
    "defaults": {
      "headers": {
        "Content-Type": "application/json"
      }
    },
  },
  "scenarios": [
    {
      "flow": [
        {
          "get": {
            "url": "/",
            "headers": {
              "access-token": "{{token}}"
            }
          }
        },     
      ]
    }
  ]
}

json 파일으로 테스트 내용을 작성해주면 된다. yml파일로 작성할 수 도 있지만 json파일이 더 친숙하기 때문에 json파일로 작성하였다.


phases": [
    {
       "duration": 60,
       "arrivalRate": 5
    }
]

phaese 부분에는 몇초동안 몇번씩 실행할지 작성해줄 수 있는데, 위의 옵션은 60초 동안 초당 5번씩 scenarios에 있는 flows들을 실행한다는 뜻이다. 위에는 flow에 get / 만 적혀있어 초당 5번만 실행되지만 10개를 작성하면 초당 50개씩 요청이 간다.


$ artillery ./test/stress.test.config.yml

해당 명령어를 터미널에 작성하면 파일에 작성한대로 테스트가 실행된다.


payload를 이용해 여러 사용자로 요청 보내기

{
   "get": {
      "url": "/users/me",
        "headers": {
           "access-token": "asdiofnasifnjaweklfn..."
         }
    }
},

우리 서비스는 모든 요청에 헤더에 토큰이 필요해서 이렇게 요청마다 넣어주어야 한다. 하지만 이건 너무 번거롭다. 또한 하나의 토큰만 사용하여 하나의 유저에 대해 테스트하는 것도 테스트의 의미가 사라진다고 생각한다.


usertoken-1
usertoken-2
usertoken-3
usertoken-4
usertoken-5
.
.
.

이렇게 csv파일에 각기 다른 유저의 토큰을 넣어주고


{
  "config": {
    "target": "http://localhost:3000",
    "phases": [
      {
        "duration": 60,
        "arrivalRate": 5
      }
    ],
    "defaults": {
      "headers": {
        "Content-Type": "application/json"
      }
    },
    "payload": {
      "path": "./tokens.csv",
      "fields": ["token"]
    }
  },
...

그리고 payload에서 csv파일을 import해준다. 그 다음 field 에서 csv에 설정한 변수를 가져와준다.


{
   "get": {
      "url": "/users/me",
        "headers": {
           "access-token": {{token}}
         }
    }
},

이제 header에 토큰을 넣어주면 여러유저의 토큰이 돌아가면서 사용될 것이다.


"scenarios": [
    {
      "flow": [
        {
          "get": {
            "url": "/",
            "headers": {
              "access-token": "{{token}}"
            }
          }
        },
        {
          "get": {
            "url": "/users/me",
            "headers": {
              "access-token": "{{token}}"
            }
          }
        },
...

그리고 모든 get 요청에 대해 시나리오를 작성해 주었다. (우리 서비스가 조회가 많이 일어나는 서비스이기 때문)


요청하기

초당 50번 요청

"phases": [
    {
      "duration": 60,
      "arrivalRate": 5
    }
],

먼저 초당 50번의 요청을 보내보자 (arrivalRate가 5이지만 flow가 10개이므로)


http.requests가 요청을 보낸 총 횟수이고
mean은 평균적 속도
p95는 예를 들어, P95 응답 시간이 50ms라면 이는 전체 요청 중 95%의 경우가 50ms 이하로 처리된다는 것을 의미한다. 5%의 경우는 50ms를 초과하여 처리된다.
P99 응답 시간이 100ms라면 이는 전체 요청 중 99%의 경우가 100ms 이하로 처리된다는 것을 의미한다. 1%의 경우는 100ms를 초과하여 처리된다.

P99와 P95는 평균(mean)보다 이상치(outlier)에 덜 민감하며, 전체 데이터 분포를 더 잘 반영한다.

결과를 보면 어쨋든 초당 50회 요청까지는 매우 빠르게 응답을 하는 것으로 확인할 수 있다.


초당 100번 요청

"phases": [
    {
      "duration": 60,
      "arrivalRate": 100
    }
],

그 다음 초당 100회 요청을 보내보자.


50회보단 느리지만 p95가 198.4ms인것을 보니 아직까지는 매우 빠르게 응답하는 것을 확인할 수 있다.


초당 200번 요청

200번 요청부턴 응답 시간이 기하급수적으로 늘었다. 50회일때는 p95가 198.4m였는데 초당 요청량을 2배로 늘렸더니 p95가 8000ms 거의 40배 가량 늘어버렸다.

이로인해 초당 200번 요청부터는 서버가 버티지 못하는 것을 깨달았다.


그래프로 확인하기

artillery run --output result.json ./test/stress.test.config.yml

artillery로 실행시에 --output option을 넣어주면 해당 스크린샷에 나온 값을을 json파일로 저장할 수 있다.


npx artillery report result.json

그리고 report 명령어를 사용하면 해당 json파일을 그래프로 시각화하여 볼 수 있다.


해당 명령어를 작성하면 html파일이 생성되는데, html파일을 열어보면 위 처럼 여러 지표들을 그래프로 시각화하여 볼 수 있다.

profile
https://www.youtube.com/watch?v=__9qLP846JE

0개의 댓글

관련 채용 정보