블로그 이미지
redkite

카테고리

분류 전체보기 (291)
00.SI프로젝트 산출물 (0)
00.센터 운영 문서 (0)
01.DBMS ============.. (0)
01.오라클 (117)
01.MS-SQL (15)
01.MySQL (30)
01.PostgreSql (0)
01.DB튜닝 (28)
====================.. (0)
02.SERVER ==========.. (0)
02.서버-공통 (11)
02.서버-Linux (58)
02.서버-Unix (12)
02.서버-Windows (2)
====================.. (0)
03.APPLICATION =====.. (11)
====================.. (0)
04.ETC =============.. (0)
04.보안 (5)
====================.. (0)
05.개인자료 (1)
06.캠핑관련 (0)
07.OA관련 (1)
Total
Today
Yesterday

달력

« » 2024.5
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

공지사항

최근에 올라온 글

24시간 365일 서버/인프라를 지탱하는 기술 - 4.2  아파치 튜닝
발제 : 문태준
http://groups.google.com/group/sysadminstudy

 

4.2    아파치 튜닝      209
        웹 서버 튜닝    209
        웹 서버가 병목현상?    209
        아파치의 병렬처리와 MPM        210
        httpd.conf 설정  216
        Keep-Alive      227
        아파치 이외의 선택방안 검토      227

 

** 이번 장에서는 웹서버에서 프로세스 또는 쓰레드 수를 제어하는 설정항목에 대해 공부를 함.

ㅇ 웹 서버 튜닝

ㅇ 웹 서버가 병목현상?


추축하지 말라! 계측하라!


여기서 살펴보는 것은 아파치 설정항목 중에서 특히 대규모 환경에서 성능에 영향을 미칠 부분에 대해 알아봄

 

ㅇ 아파치의 병렬처리와 MPM

병렬처리의 구현모델 : 멀티프로세스 / 멀티쓰레드 / 이벤트 구동 모델

아파치는 내부의 각종 기능이 모듈화에 의해 깔끔하게 분리되어 있는 것이 특징이며 병렬처리를 수행하는 코어 부분의 구현도 모듈로 되어 있다. MPM Multi Processing Module(http://httpd.apache.org/docs/2.2/ko/mod/)

 

유닉스 환경에서 대표적인 MPM은 다음의 두가지이다.
- prefork : 미리 복수의 프로세스를 생성해서 클라이언트의 접속에 대비하는 멀티프로세스 모델
- worker : 멀티쓰레드와 멀티프로세스의 하이브리드형

 

프로그래밍 모델 관점에서 본 멀티프로세스/멀티쓰레드의 차이
- 멀티프로세스에서는 기본적으로 프로세스 간에 메모리를 직접  공유하지는 않는다. 메모리 공간이 독립해 있으므로 안전한다.
- 멀티쓰레드에서는 메모리 공간 전체를 복수의 쓰레드가 공유하므로, 리소스 경합이 발생하지 않도록 주의할 필요가 있다.

  이것이 멀티쓰레드 프로그래밍이 복잡하다고 하는 이유다.
- prefork : 안정지향, 후방호환성이 높은 MPM
- worker : 확장성이 높은 MPM

 

 

성능 관점에서 본  멀티프로세스/멀티쓰레드의 차이
일반적으로 멀티쓰레드가 가볍고 빠르다. 그 이유는
- 복수의 메모리 공간을 각각 지닌 멀티프로세스보다도 메모리 공간을 공유하는 멀티쓰레드쪽이 메모리 소비량이 적다
-> 멀티프로세스의 경우에도 부모와 자식 프로세스에서 갱신되지 않는 메모리 공간은 공유(Copy on Write) 되므로 그렇게까지 현저한 차이가 나는 것은 아니다.
- 멀티쓰레드는 메모리 공간을 공유하고 있으므로, 쓰레드 전환에 걸리는 비용이 멀티프로세스보다 적다. (컨텍스트 스위치 비용)

- prefork 를 worker로 변경하더라도 하나의 클라이언트에 대한 응답시간이 고속화되는 것은 아니다
- prefork를 worker 로 변경하더라도 메모리가 충분하다면 동시에 처리할 수 있는 접속 수는 변하지 않는다.
- prefork를 worker 로 변경하더라도 대량의 컨텍스트 스위치가 없다면(동시에 병렬적으로 대량의 엑세스가 없다면) 효과는 크지 않다.

 

 

prefork 를 worker 로 변경해서 효과적인 부분
- 이용할 수 있는 메모리 용량이 그다지 크지 않은 경우나, 메모리 소비량을 줄이고자 할 경우. 이런 경우 프로세스보다 메모리 소비량이 적은 쓰레드의 이점이 살아난다.
- 컨텍스트 스위치 횟수가 많아서 그만큼의 CPU 리소스를 줄이고자 할 경우, 즉 대량의 엑세스로 인한 CPU 사용줄이 줄이고자 할 경우. 프로세스보다 쓰레드 쪽이 컨텍스트 스위치 비용은 낮으므로 CPU 소비가 줄어든다.
** 메모리 용량이 크지 않으면 오히려 메모리를 늘리는 것이 더 편하지 않을까?
** 그런데 과연 어떨 때 컨텍스트 스위치 횟수가 많다고 할 수 있을까? 튜닝책에서 나오지만 실제로 어떻게 기준을 잡아야 하는지는 모르겠다.

 

 

하나의 클라이언트에 대한 하나의 프로세스/쓰레드
prefork, worker 공통적인 것은 아파치는 클라이언트로부터 온 하나의 요청에 대해 기본적으로 하나의 프로세스 혹은 하나의 쓰레드를 할당해서 처리한다.
따라서 동시에 생성할 수 있는 프로세스/쓰레드 수가 아파치의 성능을 좌우하는 항목이 된다.
-> 프로세스/쓰레드 수를 제어하는 설정항목의 최적해를 찾는 것


ㅇ httpd.conf 설정
아파치의 안전판 MaxClients : 동시에 접속할 수 있는 클라이언트 개수의 상한값

 

1. prefork 의 경우
ServeLImit : 서버수. 이를테면 prefork 에서는 프로세스 수의 상한
MaxClient : 동시에 접속할 수 있는 클라이언트 수의 상한
prefork 에서는 양자가 거의 같은 의미임.

그러면 이 수치를 어떻게 계산할 것인가?

- /proc/PID/status 에서 특정 프로세스가 실제 사용하고 있는 물리 메모리 영역은 VmHWM 항목임. 그러나 리눅스에서는 물리 메모리를 절약하기 위해 부모 프로세스와 자식 프로세스에서 일부 메모리를 공유함. 이러한 공유부분 메모리를 고려해야 함.

VmHWM: Peak resident set size ("high water mark").
VmRSS: Resident set size.

** VmRSS와 VmHWM의 차이는 무얼까? centos linux-2.6.18 커널소스의 Documentation/filesystem/proc.txt 의 내용은 오래되어 이에 대한 설명이 없음. man proc 에도 rss만 설명이 있음. ps에서는 VmRSS 항목이 나옴.

- 부모, 자식프로세스 간 메모리를 공유하는 Copy On Write
fork 에 의해 생성되면 부모와 자식은 서로 다른 메모리 공간에서 동작하고 서로가 간섭하는 일이 없음. 그러나 fork 에 동반해서 부모로부터 자식에게 메모리의 내용을 있는 그대로 복사하지만 매우 비용이 높음. 그래서 리눅스는 fork 를 한 단계에서는 가상 메모리 공간에 매핑된 물리 메모리 영역은 복사하지 않고 부모와 자식 간에 이를 공유함. 부모 혹은 자식이 가상 메모리에 대해 쓰기를 수행하면, 해당 쓰기 작업이 수행된 영역은 더 이상 공유할 수 없으므로 그 때 처음으로 해당 영역과 연관되어 있는 물리영역만 부조 자식 간에 제각기 가지게 됨.

쓰기 작업시에 복사, fork 에 동반한 메모리 복사의 지연처리
p220 그림 4.2.4 가상 메모리의 카이 온 라이트 그림 참고

- Copy on Wirte 로 공유 메모리 사이즈 확인
공유 메모리 영역은 /proc/pid/smaps 의 데이터를 참조함으로써 확인할 수 있지만 데이터량이 많아 스크립트 등으로 확인하는 것이 좋음. RSS 프로세스 전체의 메모리, SHARED 부모 자식 프로세스간에 공유하고 있는 메모리를 확인.

- 메모리 계산 (예제)
전체 메모리량 4GB
httpd 프로세스 하나당 메모리 사용률 100MB
대략 70%는 부모와 공유한다고 했을 때 자식 프로세스 하나당 메모리 사용량은 30MB
OS 가 이용하는 메모리는 512MB
4GB-512MB=3.5GB 를 httpd 에 할당 3,500/30 = 116.66 -> 대략적인 계산이므로 100으로 설정

-MaxRequestsPerChild
Copy On Write 에 의한 메모리 공유는 시간의 경과에 따라 공유율이 하락해감. 아파치에서는 정기적으로 자식 프로세스를 종류시키고 새로운 자식 프로세스를 생성시켜 이러한 상태를 피해감. 이에 대한 설정이 MaxRequestsPerChild 임. 예를 들어 이 설정이 1024이면 하나의 프로세스당 1024개의 요청을 처리하면 해당 프로세스는  1024번째의 요청완료 직후에 자동으로 종류하고, 부모 프로세스가 새로운 자식 프로세스를 준비함.
이 설정은 mod_perl 이나 mod_php 등에서 동작하고 있는 애플리케이션이 메모리 누수(Memory Lock)을 일으키고 있는데도 이를 방치해두고 항상 계속해서 메모리를 소비하도록 할 경우의 응급처치에도 유효

 

2. worker 의 경우
하나의 프로세스 내에 복수의 쓰레드를 생성하고, 쓰레드 하나로 클라이언트 하나를 처리한다.
해당 프로세스를 복수 개 생성한다.
-> 프로세스*프로세스당 쓰레드 만큼의 쓰레드가 동시병행으로 동작

쓰레드는 프로세스의 경우와 달리, 메모리 공간을 쓰레드끼리 완전히 공유한다. 카피 온 라이트와 같은 경우를 생각할 필요가 없다.
하나의 쓰레드당 스택 영역으로 최대 8,192kb의 메모리를 필요로 한다.

MaxClient : 동시에 접속할 수 있는 클라이언트 수의 상한, 프로세스수 * 쓰레드 수
ServeLImit : 프로세스 수의 상한
ThreadLimit : 프로세스당 쓰레드 수의 상한
ThreadsPerChild : 프로세스당 쓰레드 수(ThreadLimit와 거의 같은 의미)

예를 들면 MaxClients 4096 /  ThreadsPerChild 128  = 32 프로세스

따라서 항상 ServerLlimit >= MaxClients / ThreadPerChild 라는 관계를 충족시키도록 조정한다.

여기서도 시스템에 탑재된 메모리량과 쓰레드 하나당 소비 메모리량을 저울질해서 계산한다. (쓰레드는 ps 에서 -L 옵션 이용)

** p60 ServerLimit/ThreadLImit 와 메모리의 관계 참고. 이 두가지는 아파치가 확보하는 공유 메모리 크기에 영향을 미치기때문에 필요 이상으로 높으면 쓸데없이 공유 메모리를 낭비하게 됨.


- 과부하로 MaxClients 를 변경하기 전
표면상으로 MaxClients 상한선에 도달했다고 해서 웹서버에 문제가 있다고 말을 할 수는 없다. 단지 어딘가에 문제가 있음을 나타낸다.
그림 4.2.6과 같이 DB에 과부하가 걸리는 경우에도 이러한 증상이 나타날 수 있다. 아파치 설정을 변경해서 해결할 문제는 아니다.


ㅇ Keep-Alive
경우에 따라서는 Keep-Alive 가 병목현상의 원인이 될 수 있음. p53 2.1절의 리버스 프록시 절 참조. (리버스 프록시에서는 Keep-Alive ON, 리버스 프록시와 백엔드 AP서버 사이는 Keep-Alive OFF)

 

ㅇ 아파치 이외의 선택방안 검토
아파치 장점 : 깔끔하게 모듈화된 범용적인 구조, 높은 확장성. 웹 서버 이상의 네트워크 서버로 볼 때, 아파치 이상으로 다양한 상황에 사용할 수 있는 서버는 많지 않다.
아파치 성능 : 아파치에서 멀티쓰레드와 Single Process Event Drive (SPED) 는 아키텍처 관점에서 각각 일장일단이 있고 어느 한쪽이 압도적으로 뛰어난 것은 아니다.
아파치 내부구현 : 범용적인 구조로 되어 있어서 하나의 요청에 대한 사이클 내에 필요로 하는 리소스가 모두 약간 많음.

- lighttpd
SPEED 채용, 적은 메모리로 대량의 접속을 동시병행적으로 처리하는 것을 주안에 둔 빠른 구현
아파치에 비해 범용성은 떨어지나 CPU 소모는 적음
싱글프로세스이므로 메모리 소비량이 아파치와 비교해 훨씬 적게 듬
아파치의 코어 모듈, mod_rewrite 나 mox_proxy 에 해당하는 기능은 모두 포함
FastCGI 대응, perl/php/rubby 웹애플리케이션을 고속화해서 ap서버로 이용 가능

아파치와 비교해 가장 현저한 차이는 메모리 소비량.
정적인 파일을 대량으로 전송하고자 할 경우 적합. 대량의 파일을 대량의 클라이언트로 반환할 경우에도 최소한의 리소스 소비
동적인 컨텐츠 전송시는 apache+mod_perl(mod_php) 과 lighttpd + FastCGI 조합으로 비교했을 때 그다지 성능차가 없음

Posted by redkite
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함