•
부하 테스트
◦
테스트 전제조건 정리
▪
대상 시스템 범위
▪
목푯값 설정 (latency, throughput, 부하 유지기간)
▪
부하 테스트 시 저장될 데이터 건수 및 크기
◦
아래 시나리오 중 하나를 선택하여 스크립트 작성
▪
접속 빈도가 높은 페이지
▪
데이터를 갱신하는 페이지
▪
데이터를 조회하는데 여러 데이터를 참조하는 페이지
◦
Smoke, Load, Stress 테스트 후 결과를 기록
장애의 가장 큰 원인은 바로 단일 장애 포인트
로드 밸런서, 웹서버, 어플리케이션 서버, 데이터베이스까지 모든 요소를 다중화해야한다.
고려할 것
1.
사용자
2.
처리량
3.
시간
테스트 전제조건
1.
대상 시스템 범위
2.
목표값 설정
a.
latency
b.
throughput
c.
부하 유지기간
3.
부하 테스트시 저장될 데이터 건수 및 크기
4.
스크립트 작성 : 데이터를 조회하는데 여러 데이터를 참조하는 페이지
목푯값 설정
1.
우선 예상 1일 사용자 수(DAU)를 정해봅니다.
a.
i.
월 방문자수 = 48.8M
ii.
방문자수 당 방문 페이지수 = 11.56
iii.
Avg Visit Duration = 06:40
b.
우리의 DAU = 48.8M / 30 = 1.62M = 162만명
2.
피크 시간대의 집중률을 예상해봅니다. (최대 트래픽 / 평소 트래픽)
a.
방문 수 * 평균 페이지뷰 * 1페이지당 평균 바이트
b.
최대 트래픽 / 평소 트래픽 = 대략 10배
3.
1명당 1일 평균 접속 혹은 요청수를 예상해봅니다.
a.
20번
4.
이를 바탕으로 Throughput을 계산합니다.
•
Throughput : 1일 평균 rps ~ 1일 최대 rps
◦
1일 사용자 수(DAU) x 1명당 1일 평균 접속 수 = 1일 총 접속 수
▪
162만명 * 20번 = 1일 3240만번
◦
1일 총 접속 수 / 86,400 (초/일) = 1일 평균 rps
▪
3240만번 / 86,400 초 = 1일 평균 375 rps
◦
1일 평균 rps x (최대 트래픽 / 평소 트래픽) = 1일 최대 rps
▪
375 rps * 10배 = 1일 최대 3750 rps = 1초당 3750번 요청
•
Latency : 일반적으로 50~100ms이하로 잡는 것이 좋습니다.
◦
50ms
•
사용자가 검색하는 데이터의 양, 갱신하는 데이터의 양 등을 파악해둡니다.
VUser 구하기
•
Request Rate: measured by the number of requests per second (RPS)
◦
평균 375
◦
최대 3750
•
R: the number of requests per VU iteration
◦
1인당 요청수 20 번
•
T: a value larger than the time needed to complete a VU iteration
◦
20번 * 0.3 ms + 1000ms(1s) = 1006 ms = 1.006s
•
VU: the number of virtual users
•
1일 평균 = 375 rps * 1.006s / 20 = 18.86 명 = 약 18명
•
1일 최대 = 3750 rps * 1.006s / 20 = 188.625 명 = 약 188명
T = (R * http_req_duration) (+ 1s) ; 내부망에서 테스트할 경우 예상 latency를 추가한다
VUser = (목표 rps * T) / R
Plain Text
복사
•
가령, 두개의 요청 (R=2)이 있고, 왕복시간이 0.5s, 지연시간이 1초라고 가정할 때 (T=2), 계산식은 아래와 같다.
VU = (300 * 2) / 2 = 300
테스트 계획
1.
smoke test
a.
vuser = 1
b.
duration = 1m
c.
p(99) < 50ms
2.
load test 18
a.
vuser = 18
b.
duration 1m
3.
load test 200
a.
vuser = 200
b.
duration 1m
4.
stress test
a.
vuser
b.
duration 1m
SmokeTest 결과
// smoke.jsimport http from 'k6/http';import { check, group, sleep, fail } from 'k6';export let options = {
stages: [
{duration: '1m', target: 1} //duration 동안 현재 사용자를 target 명으로 유지 ], thresholds: {
http_req_duration: ['p(99)<1000'], // 99% of requests must complete below 1s },};const BASE_URL = 'https://infra.subway-mhson.kro.kr';function getPage(APIS) {
for (const api of APIS) {
const response = http.get(api); check(response, {
'response code was 200': (response) => response.status == 200, }); sleep(4); }
}
export default function () {
//출발역 조회 //도착역 조회 //경로 검색 const GET_PAGE_APIS = [
`${BASE_URL}/stations`, `${BASE_URL}/stations`, `${BASE_URL}/paths?source=1&target=365` ]; getPage(GET_PAGE_APIS);};
JavaScript
복사
테스트 계획
1.
30초 동안 VUser 0명 → 1명 증가.
2.
1분 동안 VUser 1명 유지.
3.
30초 동안 VUser 1명 → 0명 감소.
4.
99%의 요청이 각각 50ms 미만으로 완료되어야 한다.
테스트 결과
•
모든 요청 성공.
•
95%의 요청 응답시간 1.11s 으로 예상 latency 인 50ms 보다 한참 큰 값
LoadTest 결과
보통 30분 - 2시간을 기준으로 테스트하지만, 나는 돈이 없는 가난한 개발자놈… 1분으로 족친다
// load.jsimport http from 'k6/http';import { check, group, sleep, fail } from 'k6';export let options = {
stages: [
{duration: '1m', target: 100} //duration 동안 현재 사용자를 target 명으로 유지 ], thresholds: {
http_req_duration: ['p(99)<50'], // 99% of requests must complete below 50ms },};const BASE_URL = 'https://infra.subway-mhson.kro.kr';function getPage(APIS) {
for (const api of APIS) {
const response = http.get(api); check(response, {
'response code was 200': (response) => response.status == 200, }); sleep(4); }
}
export default function () {
//출발역 조회 //도착역 조회 //경로 검색 const GET_PAGE_APIS = [
`${BASE_URL}/stations`, `${BASE_URL}/stations`, `${BASE_URL}/paths?source=1&target=365` ]; getPage(GET_PAGE_APIS);};
JavaScript
복사
결과
•
응답은 잘 받았으나
•
http_req_duration 값은 기대치였던 50ms 보다 한참 못미치는 9s 를 기록하였다.
CPU 사용 결과
StressTest 결과
500명까지 올려보자! 어떻게 되나 보자~!~!!!!
// stress.jsimport http from 'k6/http';import { check, group, sleep, fail } from 'k6';export let options = {
stages: [
{duration: '10s', target: 0}, {duration: '1m', target: 150}, //duration 동안 현재 사용자를 target 명으로 유지 {duration: '1m', target: 300}, {duration: '1m', target: 500}, {duration: '10s', target: 0}
], thresholds: {
http_req_duration: ['p(99)<50'], // 99% of requests must complete below 50ms },};const BASE_URL = 'https://infra.subway-mhson.kro.kr';function getPage(APIS) {
for (const api of APIS) {
const response = http.get(api); check(response, {
'response code was 200': (response) => response.status == 200, }); sleep(4); }
}
export default function () {
//출발역 조회 //도착역 조회 //경로 검색 const GET_PAGE_APIS = [
`${BASE_URL}/stations`, `${BASE_URL}/stations`, `${BASE_URL}/paths?source=1&target=365` ]; getPage(GET_PAGE_APIS);};
JavaScript
복사
결과
좆망했다.
테스트 중 체크한 cpu 사용량
60% 가량의 패킷이 손실되었음을 확인함
실제 응답률은 40%도 안됨
중간부터 계속 connection peer 에러 발생
Grafana 대시보드 구성하기
influx DB
•
◦
docker 이용하여 설치
grafana 설치
// Some code
docker run -p 8086:8086 \
-v influxdb:/var/lib/influxdb \
-e DOCKER_INFLUXDB_INIT_MODE=upgrade \
-e DOCKER_INFLUXDB_INIT_USERNAME=admin \
-e DOCKER_INFLUXDB_INIT_PASSWORD=admin \
-e DOCKER_INFLUXDB_INIT_ORG=subway \
-e DOCKER_INFLUXDB_INIT_BUCKET=myk6db \
influxdb
Plain Text
복사
참고
•
트래픽, 방문자수 대략 확인