[인프라 공방 5기] 2주차 - 성능 진단하기(2) : 실습
인프라 공방 5기 : NEXTSTEP 에서 진행하는 ‘인프라 공방 5기’ 2주차 ‘성능 진단하기’ 실습에 대한 내용을 정리한다.
학습 목표
- USE 방법론과 쓰레드 덤프 활용을 통한 서버 진단
- webpagetest, pagespeed 활용을 통한 웹 성능 예산 고민
- 성능 목표치 설정 및 부하테스트 수행
1단계 - 웹 성능 테스트
요구사항
- 웹 성능 테스트
- 웹 성능 예산을 작성 - 성능 지표 참고
- WebPageTest, PageSpeed 등 테스트해보고 개선이 필요한 부분을 파악
요구사항 설명
- 인프라공방 지하철 모니터링 git
- README 에 있는 질문에 답을 추가한 후 PR을 보내고 리뷰요청
타사(경쟁사) 서비스 비교
내 서비스 진단 결과(PageSpeed 기준)
타 서비스 비교(PageSpeed 기준)
서울교통공사 | 네이버지도 | 카카오맵 | 내 서비스 | 경쟁사 평균 | 경쟁사 평균 대비 20% 오차 | |
---|---|---|---|---|---|---|
FCP(s) | 7.3 | 2.2 | 1.7 | 14.6 | 3.7 | 4.4 |
Speed Index(s) | 13.3 | 5.2 | 7.0 | 14.6 | 8.5 | 10.2 |
LCP(s) | 8.0 | 7.5 | 4.7 | 15.2 | 6.7 | 8.0 |
TTI(s) | 8.9 | 6.8 | 4.4 | 15.3 | 6.7 | 8.0 |
TBT(ms) | 410 | 350 | 100 | 560 | 287 | 344 |
CLS | 0 | 0.03 | 0.005 | 0.042 | 0.01 | 0.012 |
Total Score | 39 | 57 | 73 | 32 | 56 | 44.8 |
사용자는 응답시간이 20% 이상일 때 인식한다. 즉, 경쟁사 대비 20% 이상의 성능차이가 발생하지 않도록 하는 것이 좋다.
즉, 나의 서비스가 지켜야할 최소한의 성능 예산 목표치는 위 표에 나타난 “경쟁사 평균 대비 20% 오차”이다.
개선 하기
FCP
- 텍스트 압축 사용 (9.3s)
- 렌더링 차단 리소스 제거 (0.75s)
- 사용하지 않는 CSS 줄이기 (0.15s)
TBT
- 기본 스레드 작업 최소화하기 (2.3s)
- 자바스크립트 실행 시간 단축 (1.5s)
LCP
- 텍스트 압축 사용 (9.3s)
- 사용하지 않는 자바스크립트 줄이기 (3.45s)
- 렌더링 차단 리소스 제거 (0.75s)
- 콘텐츠가 포함된 최대 페인트 이미지 미리 로드 (0.33s)
- 사용하지 않는 CSS 줄이기 (0.15s)
CLS
- 이미지 요소에 width 및 height가 명시되어 있지 않음. (명시하기)
- 대규모 레이아웃 변경 피하기
2단계 - 부하테스트
요구사항
- 테스트 전제조건 정리
- 대상 시스템 범위
- 목푯값 설정 (latency, throughput, 부하 유지기간)
- 부하 테스트 시 저장될 데이터 건수 및 크기
- 각 시나리오에 맞춰 스크립트 작성
- 접속 빈도가 높은 페이지
- 데이터를 갱신하는 페이지
- 데이터를 조회하는데 여러 데이터를 참조하는 페이지
- Smoke, Load, Stress 테스트 후 결과를 기록
k6 사용방법
- k6 : 부하테스트 툴
k6 설치
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
$ echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
$ sudo apt-get update
$ sudo apt-get install k6
Test script 작성
- k6는 javascript 기반으로 테스트 script를 작성한다.
// script.js
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
//http.get('http://test.k6.io');
http.get('http://본인이 부하테스트를 희망하는 사이트를 여기에 입력해주세요.');
sleep(1);
}
실행
$ k6 run --vus 10(가상 사용자 수) --duration 30s(부하시간) --out csv=test.csv(출력되는 결과물 형식) script.js(실행할 스크립트)
테스트 설정값 구하기
목표 rps 구하기
- 1일 예상 사용자 수(DAU) 정의
- 피크 시간대 집중률 예상 (최대 트래픽 / 평소 트래픽)
- 1명당 1일 평균 접속 혹은 요청수 예상
- Throughput 계산(1일 평균 rps ~ 1일 최대 rps)
- 1일 총 접속 수 = 1일 사용자 수(DAU) x 1명당 1일 평균 접속 수
- 1일 평균 rps = 1일 총 접속 수 / 86,400 (초/일)
- 1일 최대 rps = 1일 평균 rps x 피크 시간대 집중률(최대 트래픽 / 평소 트래픽)
VUser 구하기
- Request Rate(rps) : 1초당 요청 수
- VU : 가상 사용자 수
- R : VU 반복당 요청 수
- T : VU 반복을 완료하는 데 필요한 시간보다 큰 값
T = (R * http_req_duration) (+ 1s) // 내부망에서 테스트할 경우 예상 latency를 추가한다, http_req_duration : 요청 왕복 시간
VUser = (목표 rps * T) / R
가령, 두개의 요청(R=2)이 있고, 왕복시간(http_req_duration)이 0.5s, 지연시간이 1초라고 가정할 때, T=2 이다.
목표 rps를 300이라 할 때, VU = (300 * 2) / 2 = 300
이다.
테스트 기간
- 일반적으로 Load Test는 보통 30분 ~ 2시간 사이로 권장
- 부하가 주어진 상황에서 DB Failover, 배포 등 여러 상황을 부여하며 서비스의 성능을 확인한다.
대시보드 구성
influx db
- 특징
- influx는 오픈 소스 기반의 시계열 데이터베이스이다.(시간 흐름을 중심으로 데이터 관리)
- 운영 모니터링, 애플리케이션 매트릭스, 사물인터넷 센서 데이터, 실시간 분석 등 분야에서 최적화 되어있다.
- influx db는 8086 포트 점유
- 설치
$ sudo curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
$ sudo echo "deb https://repos.influxdata.com/ubuntu bionic stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
$ sudo apt update
$ sudo apt install influxdb
- 실행
# 서비스 중지
$ sudo systemctl stop influxdb
# 서비스 시작
$ sudo systemctl start influxdb
# 서버 재시작 후 자동 실행
$ sudo systemctl enable --now influxdb
$ sudo systemctl is-enabled influxdb
# 서비스 상태 확인
$ sudo systemctl status influxdb
# 서비스 헬스 체크
$ curl {server_ip}:8086/health
- 설정
$ sudo nano /etc/influxdb/influxdb.conf
[http]
# Determines whether HTTP endpoint is enabled.
enabled = true <-- 주석 제거
# Determines whether the Flux query endpoint is enabled.
# flux-enabled = false
- 계정 생성 및 접속
# 계정 생성
$ curl -XPOST "http://{server_ip}:8086/query" --data-urlencode "q=CREATE USER {user_name} WITH PASSWORD '{your_password}' WITH ALL PRIVILEGES"
# 계정 접속
$ influx -username '{user_name}' -password '{your_password}'
# Query TEST
$ curl -G http://{server_ip}:8086/query -u {user_name}:{your_password} --data-urlencode "q=SHOW DATABASES"
grafana
특징
- grafana 시계열 데이터랑 메트릭 정보를 보여주기 위한 오픈소스 대시보드 툴
- Graphite, Elasticsearch, OpenTSDB, Prometheus, InfluxDB, Cloudwatch 등을 데이터 소스로 이용
- grafana는 3000 포트 점유
설치
$ sudo apt-get update && sudo apt-get upgrade -y
$ sudo apt-get install -y apt-transport-https
$ sudo apt-get install -y software-properties-common wget
$ wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
$ echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
$ sudo apt-get update
$ sudo apt-get install grafana
실행
$ service grafana-server start
접속
- 브라우저로
{server_ip}:3000
접속 - 초기 계정(id/password) :
admin / admin
Datasource 설정
- Configuration > Data Source
- URL에 influxDB 접속 URL 입력
- Database 에 본인의 influxDB에서 생성된 DB 이름 입력
- User/Password 에 본인이 생성한 계정을 입력
Dashboard 설정
- Dashboard > import
- k6 > InfluxDB 선택
테스트 시작
$ k6 run --out influxdb=http://{server_ip}:8086/{database} {test_script.js}
- Dashboard 화면
로깅, 모니터링
요구사항
- 애플리케이션 진단하기 실습을 진행해보고 문제가 되는 코드를 수정
- 로그 설정하기
- Cloudwatch로 모니터링
로그 설정하기
Application Log 파일로 저장하기
- 회원가입, 로그인 등의 이벤트에 로깅을 설정
- 경로찾기 등의 이벤트 로그를 JSON으로 수집
주의사항
- Avoid side effects
- logging으로 인한 애플리케이션 동작에 영향을 미쳐서는 안된다.
- ex) logging 시점에 NPE가 발생해 프로그램이 정상적으로 동작하지 않는 상황이 발생하면 안됨
- Be concise descriptive
- 각 Logging에는 데이터와 설명이 모두 포함되어있어야 함
- Log method arguments and return values
- 메소드의 Input, Output을 로그로 남기면 Debugger를 사용하지 않아도 됨.(Debugger를 사용할 수 없는 상황에서 유용)
- AOP를 활용하여 메소드 앞, 뒤 부분에 발생할 중복 코드를 제거한다.
- Delete personal information
- 로그에 사용자의 개인정보(전화번호, 계좌번호, 패스워드, 주소 등)를 남기지 않는다.
logging level
ERROR
: 예상하지 못한 심각한 문제가 발생하여 즉시 조치 필요WARN
: 로직상 유효성 확인, 예상 가능한 문제로 인한 예외처리 등. 서비스 운영은 가능하지만 주의해야 함INFO
: 운영에 참고할만한 사항으로 중요한 비즈니스 프로세스를 로깅DEBUG/TRACE
: 개발 단계에서만 사용. 운영 단계에서는 사용하지 않음
logback 설정 참고
- https://bamdule.tistory.com/29 <- 정리 잘되어 있는 블로그
Nginx Access Log 설정하기
- Docker의 volume 옵션을 통해 호스트 경로와 도커 경로를 마운트 한다.
$ docker run -d -p 80:80 -v /var/log/nginx:/var/log/nginx nextstep/reverse-proxy
cAdvisor
- 도커 상태 모니터링
- 설치
docker run \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --volume=/dev/disk/:/dev/disk:ro \ --publish=8080:8080 \ --detach=true \ --name=cadvisor \ google/cadvisor:latest
- 모니터링에 필요한 디렉토리 볼륨 지정(보안을 위해 읽기전용 사용
:ro
) - 8080포트 개방 필요
Cloudwatch로 모니터링
- IAM Role 설정 (in 모니터링 대상 EC2)
- 설치
# 설치
$ curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O
# 파이썬 설치
$ sudo apt install python
# 실행
$ sudo python ./awslogs-agent-setup.py --region ap-northeast-2
# ㄴ Access Key, Secret Key 등 하지 말것! IAM Role 설정으로 충분함
Cloudwatch로 로그 수집하기
- 설정파일 수정
$ sudo vi /var/awslogs/etc/awslogs.conf
[/var/log/syslog]
datetime_format = %b %d %H:%M:%S
file = /var/log/syslog
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = [로그그룹 이름]
[/var/log/nginx/access.log]
datetime_format = %d/%b/%Y:%H:%M:%S %z
file = /var/log/nginx/access.log
buffer_duration = 5000
log_stream_name = access.log
initial_position = end_of_file
log_group_name = [로그그룹 이름]
[/var/log/nginx/error.log]
datetime_format = %Y/%m/%d %H:%M:%S
file = /var/log/nginx/error.log
buffer_duration = 5000
log_stream_name = error.log
initial_position = end_of_file
log_group_name = [로그그룹 이름]
[로그그룹 이름]
: 개인의 github id로 지정
$ sudo service awslogs restart
Cloudwatch로 메트릭 수집하기
$ wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
$ sudo dpkg -i -E ./amazon-cloudwatch-agent.deb
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "root"
},
"metrics": {
"metrics_collected": {
"disk": {
"measurement": [
"used_percent",
"used",
"total"
],
"metrics_collection_interval": 60,
"resources": [
"*"
]
},
"mem": {
"measurement": [
"mem_used_percent",
"mem_total",
"mem_used"
],
"metrics_collection_interval": 60
}
}
}
}
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
# -- status -- #
{
"status": "running",
"starttime": "2022-05-02T12:25:34+00:00",
"configstatus": "configured",
"cwoc_status": "stopped",
"cwoc_starttime": "",
"cwoc_configstatus": "not configured",
"version": "1.247350.0b251780"
}
USE 방법론을 활용하기 용이하도록 대시보드 구성
- AWS 검색창에 Cloudwatch 입력
- 위젯 추가 > 행 선택
- 지표 선택
- 검색어에 모니터링을 원하는 필드 입력
- CPU Utilization, Network In / Out, mem_used_percent, disk_used_percent 등 추가
- 최종 대시보드 구성 모습
참고
- 인프라 공방 5기 - 강의자료
댓글남기기