티스토리 뷰
이 포스팅은, 서버/인프라를 지탱하는 기술을 읽고 진행하는 스터디의 내용을 정리하였습니다.
성능이란 무엇일까?
- 암달의 법칙
성능 개선율 = 1/((1-P) + P/S)
P: 개선 가능한 부분의 비율
S: 개선된 정도
즉, 성능 개선에는 한계가 생길 수 밖에 없다는 것을 인지하고 작업하여야 한다.
튜닝은 아래의 단계로 진행된다.
1) 원인파악 : 병목지점 파악
2) 목표설정
3) 튜닝실시
4) 개선율 확인
5) 결과 정리 및 반영
결국, 튜닝이란 부하의 원인을 알고 이를 제거하는 것을 의미한다.
그렇다면 부하는 어떻게 확인할까?
우선, 부하를 계측하고자 할 때 top, uptime 등의 툴을 사용하여 Load Average를 확인한다.
Load Average가 낮은데 전송량이 오르지 않는 경우 소프트웨어 설정이나 오류, 네트워크, 원격 호스트 측에 원인이 없는지 확인하여야 한다.
Load Average가 높은 경우 sar,vmstat 등으로 시간 경과에 따라 CPU 사용률이나 I/O 대기율 추이를 확인하여야 한다.
-
CPU 부하가 높은 경우
User / Kernel 프로그램 중 원인을 확인
프로세스 상태나 CPU 사용시간 등을 통해 원인이 되는 프로세스 확인
strace 등을 통해 병목지점을 좁혀나간다. -
I/O 부하가 높은 경우
ps로 특정 프로세스가 극단적으로 메모리를 소비하고 있는지 확인
입출력이 많아 부하가 높다면, 캐시에 필요한 메모리가 부족한 경우이다. 메모리 증설 혹은 데이터분산/캐시서버 도입 등을 검토한다. 프로그램을 개선하여 I/O빈도를 줄이는 것도 검토한다.
그 외에 Swap이 발생해서 디스크 액세스가 이루어지는 경우가 있을 수 있다.
그렇다면 Load Average가 보고하는 부하는 어떻게 계산될까?
H/W는 주기적으로 CPU에 Interrupt 신호를 보낸다. 이를 타이머 인터럽트라고 한다. 이 중단마다 CPU는 시간을 진행시키거나 실행중인 프로세스가 CPU를 얼마나 사용했는지를 계산하는 등 시간에 관련된 처리를 수행한다. 이 타이머 인터럽트마다 Load Average 값이 계산된다.
커널은 타이머 인터럽트가 발생했을 때 실행 가능 상태인 Task와 I/O 대기인 Task의 개수를 세어둔다. 그 값을 단위시간으로 나눈 것이 Load Average 값으로 보고된다.
즉, 부하란, 처리를 실행하려고 해도 실행할 수 없어서 대기하고 있는 프로세스의 수를 의미한다.
-
Task란 무엇일까
우선, 프로세스는 프로그램이 OS에 의해 실행되고 있을 때 그 실행단위가 되는 개념이다. 프로세스는 커널 내부에서의 실행단위를 나타내는 Task와는 구별되긴하지만 넓은 의미에서는 거의 같다.
프로세스란 '프로그램의 명령'과 '실행시에 필요한 정보' 조합의 오브젝트를 말한다.
리눅스 커널은 프로세스마다 프로세스 디스크립터라는 관리용 테이블을 생성한다. 이 프로세스 디스크립터에 각종 실행시 정보가 저장된다.
리눅스 커널은 이 프로세스 디스크립터 군을 우선도가 높은 순으로 재배열해서 실행순으로 'Process=Task'가 실행되도록 조정한다. 이 조정 역할을 하는 것이 프로세스 스케줄러이다. -
Load Average로 환산되는 대기상태
TASK_RUNNING: CPU를 사용하고자 해도 다른 프로세스가 CPU를 사용하고 있어서 기다리고 있는 프로세스
TASK_UNINTERRUPTIBLE: 계속해서 처리하고자 해도 디스크 입출력이 끝날 때까지 기다려야만 하는 프로세스
즉, 키보드 입력대기나 sleep에 의한 대기는 프로그램이 스스로 명시적으로 기다리는 것이므로 Load Average에 포함되지 않는다. 원격호스트로부터의 데이터 착신대기도 언제 데이터가 올지 불확실하므로 포함되지 않는다.
부하를 기준으로 보면 일반적으로 WAS는 CPU bound, DB는 I/O bound 서버이다.
그렇다면 CPU 사용율은 어떻게 계산될까?
Load Average는 CPU에 엮인 실행큐가 유지하고 있는 프로세스 디스크립터의 수를 세었다. 또한 Load Average값이 저장되는 영역은 커널 내의 전역변수 배열이었다.
CPU 사용률의 계산 결과는 전역변수 배열이 아닌, 각 CPU용으로 준비된 전용 영역에 저장된다. CPU별로 지닌 영역에 데이터를 저장하므로 sar 등에서 CPU별 정보를 얻을 수 있는 것이다.
커널은 프로세스 전환을 위해서 각 프로세스가 생성된 후부터 어느정도 CPU 시간을 이용했는지를 프로세스별로 기록하고 있다. 이를 프로세스 어카운팅이라 한다.
스케줄러는 이 기록을 바탕으로 CPU 시간을 지나치게 사용하고 있는 프로세스의 우선도를 낮추거나 일정 이상으로 계산을 수행했다면 다른 프로세스로 CPU를 내어주는 작업을 수행한다.
그렇다면 I/O는 어떻게 이루어질까?
리눅스는 한번 디스크에서 읽어들인 데이터는 가능한 한 메노리에 캐시를 해서 다음 번 이후의 디스크 읽기가 고속으로 수행되도록 조정한다. 이렇게 메모리에 읽어들인 데이터의 캐시를 페이지 캐시라고 한다.
리눅스는 메모리 영역을 4KB 블록단위로 관리한다. 이 4KB 블록을 페이지라고 한다.
즉 디스크로부터 데이터를 읽어들이는 것은 다름 아닌 페이지 캐시를 구축하는 것이다. 읽어들인 데이터는 페이지 캐시에서 사용자 공간으로 전송된다.
따라서 처리할 데이터량에 비례해서 메모리를 증설하는 것이 I/O부하를 줄이는 가장 효과적인 방법이다. 메모리를 증설할 수 없을 경우에는 데이터를 분할해서 각각의 서버에 위치시키는 것을 검토하여야 한다. 데이터를 적절하게 분할하면 단순히 서버 대수를 늘린만큼 디스크 I/O 회수만 줄어드는 것이 아니라, 캐시에 올릴 데이터의 비율이 늘어나므로 상당한 전송량 향상을 기대할 수 있다.
'Infra Structure > .system' 카테고리의 다른 글
HTTP 완벽가이드 스터디 #1 (0) | 2019.08.04 |
---|---|
Docker #1 (0) | 2019.07.21 |
네트워크(L1,L2)의 다중화(Bonding 드라이버, RSTP) (1) | 2019.04.10 |
MySQL Replication이란? (0) | 2019.04.07 |
Reverse Proxy란? (0) | 2019.04.06 |