배경
스트레스 테스트 도구 왜 사용하나?
- API 서버, 웹 어플리케이션 서버를 만든 뒤 성능 테스트를 하기 위해
- 한 마디로, 서버가 얼마만큼의 요청을 견디는가?
이점
- 병목 지점을 찾을 수 있다
- 사용자 증가에 따라 언제즈음 서버를 늘릴 수 있는지에 대한 트래픽 기준을 얻을 수 있다
- 동시 접속사, 일일 사용자의 한계치를 예측할 수 있다
- OOM(out of memory) 문제 방지. 코드에 문법적, 논리적 문제가 없어도 하드웨어 제약 때문에 서비스가 중단되는 문제를 사전에 예방하는데 도움이 된다
도구 종류
- ab
- Artillery
- nGrinder
- Gatling
- Tsung
- JMeter
nodejs에서 가볍게 쓰려면 Artillery, 정교하게 측정하려면 nGrinder, JMeter 등을 사용
Artillery란?
- Node.js로 작성된 스트레스 테스트 도구
Artillery의 특징
- HTTPS, Socket.io, Websocket 등 다양한 프로토콜 지원
- 시나리오 테스트 가능
- JS로 로직 작성 가능
- statsd 지원. Datadog나 InfluxDB 등에 실시간으로 결과 등록 가능
- 리포트 페이지 제공
구현
Node.js 설치
생략
Artillery 설치
https://www.artillery.io/docs/guides/getting-started/installing-artillery
npm install -g artillery@latest
npm i -D artillery
전역 설치가 싫다면..
간단 테스트
요청
quick
명령어로 가볍게 테스트해볼 수 있다.
npx artillery quick --count 100 -n 50 http://localhost:3000/raffles/478
localhost에 100명의 가상 유저가 50회씩 요청하도록 해줘(총 5000회 요청)
--count
: 가상 사용자 수-n
: 요청 횟수--rate
: 초당 요청
결과
...
Summary report @ 18:22:39(+0900)
http.codes.200: ................................................................ 5000
http.request_rate: ............................................................. 206/sec
http.requests: ................................................................. 5000
http.response_time:
min: ......................................................................... 39
max: ......................................................................... 928
median: ...................................................................... 468.8
p95: ......................................................................... 584.2
p99: ......................................................................... 804.5
http.responses: ................................................................ 5000
vusers.completed: .............................................................. 100
vusers.created: ................................................................ 100
vusers.created_by_name.0: ...................................................... 100
vusers.failed: ................................................................. 0
vusers.session_length:
min: ......................................................................... 22111.6
max: ......................................................................... 23770.2
median: ...................................................................... 23630.3
p95: ......................................................................... 23630.3
p99: ......................................................................... 23630.3
vusers.completed: 100 -> 100명의 가장 유저의 수행이 모두 성공
vusers.created: 100
vusers.created_by_name.0: 100
vusers.failed: 0 -> 실패는 0개
http.codes.200: 5000
http.request_rate: 206/sec
http.requests: 5000 -> 5000회 요청
http.response_time:
min: 39 -> 가장 빠른 것이 0.039 sec
max: 928 -> 가장 느린 건 0.928 sec
median: 468.8 -> 중간 값 0.468 sec
p95: 584.2 -> 뒤에서 6번째(95번째)로 느린 사람이 0.584 sec
p99: 804.5 -> 뒤에서 2번째(99번째)로 느린 사람이 0.804 sec
p95, p99 차이가 낮으면 성능이 좋다는 의미라 한다. 왜냐하면 편차가 낮을 수록 비슷한 속도로 처리되었다는 의미이기 때문이다.
주의
- 실제 서비스 중인 서버에 테스트할 경우 중단될 수 있고
- AWS, GCP 클라우드의 종량제 요금 사용중일 경우, 요금 과다 청구 발생 할 수 있다
locallhost에서는 스트레스 테스트를 하더라도 큰 문제가 없다
해결 방법
- 실제 서비스에 부하 테스트하지 말고
- 실제 서버와 같은 사양의 서버(staging 서버)를 만들어서 그 서버에 부하 테스트를 진행하는 것이 좋다
상세 테스트
Artillery 스크립트 작성
스크립트 양식
- JSON
- YAML
요소
- target : 인스턴스로 접속할 url
- duration : 성능 측정 시간
- arrivalRate : 매초마다 새 가상 유저가 생성되는가
시나리오 설정 파일 옵션
"config" 영역
- target : 테스트 할 앱의 url. 서버 주소
- phases: 테스트 요청 시간과 비율.
{"duration": 60, "arrivalRate": 30}
은 60초 동안 매초 30개의 요청을 보내주세요라는 의미 - defaults : 뒤에서 테스트할 시나리오의 기본값 설정
- payload : 임의 데이터 보내기 위해 사용. csv 파일로 실제 데이터를 전송하도록 할 수도 있음
- socketio : 소켓 테스트 가능하다.
- query : socket들이 들어오는 주소 끝에 roomID로 쿼리를 다고 있기에, 이 쿼리 부분을 작성해주는 것. 방 생성 시 roomID가 달라져서 이 부분을 바꿔주는 것이 번거로울 수 있음
- plugins : 플러그인 설정. tls: configure how Artillery handles self-signed certificates
- ensure : 에러나 지연시간에 대해 성공 조건 세팅
- processor : 커스텀 js 코드 load
"Scenario" 영역
- name : 시나리오 명
- flow : 시나리오에서 진행하는 테스트 동작 순서대로 작성
- capture : 응답으로 받은 데이터를 변수에 저장하는 기능. 추후 다른 요청에서 사용할 수 있다
- match : 응답 데이터가 원하는 값이 오는지 확인 가능
- weight : 시나리오에 대한 가중치. 이 값이 높으면 해당 시나리오가 더 많이 발생
실제 코드
loadtest.json
{
"config": {
"target": "http://localhost:8001",
"phases": [
{
"duration": 60,
"arrivalRate": 30
}
]
},
"scenarios": [
{
"flow": [
{
"get": {
"url": "/"
}
},
{
"post": {
"url": "/auth/login",
"json": {
"email": "test1@test.com",
"password": "123123"
}
}
},
{
"get": {
"url": "/hashtag?hashtag=test"
}
}
]
}
]
}
나는 GET요청만 테스트하고 싶기에 이렇게 수정했다.
{
"config": {
"target": "http://localhost:3000",
"phases": [
{
"duration": 60,
"arrivalRate": 100
}
]
},
"scenarios": [
{
"flow": [
{"get": {
"url": "/raffles/478"
}}
]
}
]
}
Reference
'Research > Testing' 카테고리의 다른 글
test_nGrinder의 지표를 성능 테스트 지표로 사용해도 될 것인가에 대한 고민 (0) | 2023.02.28 |
---|---|
부하테스트 단계와 발생 문제 유형 (1) | 2023.02.24 |
Test_AB(Apache Benchmark)로 간단히 테스트하기 (0) | 2023.02.23 |
성능 테스트란 무엇일까 (0) | 2023.02.23 |
DB 성능 측정 실험에 대한 논의 (0) | 2023.02.15 |
댓글