[인프라 공방 5기] 2주차 - 성능 진단하기(2) : 실습

7 분 소요

인프라 공방 5기 : NEXTSTEP 에서 진행하는 ‘인프라 공방 5기’ 2주차 ‘성능 진단하기’ 실습에 대한 내용을 정리한다.



학습 목표

  • USE 방법론과 쓰레드 덤프 활용을 통한 서버 진단
  • webpagetest, pagespeed 활용을 통한 웹 성능 예산 고민
  • 성능 목표치 설정 및 부하테스트 수행


1단계 - 웹 성능 테스트

요구사항

요구사항 설명

타사(경쟁사) 서비스 비교

내 서비스 진단 결과(PageSpeed 기준)

img


타 서비스 비교(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% 오차”이다.


개선 하기

img

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

img

image

  • URL에 influxDB 접속 URL 입력

image

  • Database 에 본인의 influxDB에서 생성된 DB 이름 입력
  • User/Password 에 본인이 생성한 계정을 입력

Dashboard 설정

img

image

  • k6 > InfluxDB 선택

테스트 시작

$ k6 run --out influxdb=http://{server_ip}:8086/{database} {test_script.js}
  • Dashboard 화면

image


로깅, 모니터링

요구사항

  • 애플리케이션 진단하기 실습을 진행해보고 문제가 되는 코드를 수정
  • 로그 설정하기
  • 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 설정 참고


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)

image

image

  • 설치
# 설치
$ 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 입력

img

  • 위젯 추가 > 행 선택

img

  • 지표 선택

img

  • 검색어에 모니터링을 원하는 필드 입력
    • CPU Utilization, Network In / Out, mem_used_percent, disk_used_percent 등 추가

img

  • 최종 대시보드 구성 모습


참고




댓글남기기