아파치 MPM 모드와 nginx 비교(apache 2.4 vs nginx)
1. MPM 이란?
Multi-Processing Module
apache 가 받아 들인 요청을 처리 하기 위해 'child processes'에게 분배하는 방식을 말합니다.
Prefork
1) 실행중인 프로세스 복제하여 실행 (메모리 영역까지 같이 복제)
2) 프로세스가 소비하는 메모리가 많음.
3) 응답프로세스를 미리 띄워놓고 클라이언트 요청 시 자식 프로세스가 반응하게 되는 방식.
4) 안전하지 않은 제 3자가 만든 모듈 사용 가능
5) 디버깅이 빈약한 플랫폼에서 쉬운 디버깅 가능
6) 일반적으로 single CPU 또는 Dual CPU에서 성능이 좋음
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
l StartServer
아파치서버의 자식 프로세스 개수 지정
l MinSpareServers, MaxSpareServers
부하가 적어서 MinSpareServers 개수 보다 적었을 경우 최소한 이 개수 만큼 아파치가 유지하려 하며, 부하가 증가하여 프로세스 개수가 많아질 경우에 MaxSpareServers 개수 이하로 줄이려고 아파치가 구동 됩니다. 절대적인 수치는 아닙니다.
l MaxClient
초기 시작시 실행가능한 최대 아파치 자식 프로세스의 개수를 지정
worker방식의 MaxClient 와는 다른 의미가 다르지만 클라이언트의 요청을 처리하는 용량을
말하므로 비슷한 의미로 보시면 됩니다.
l MaxReqeustPerChild
클라이언트들의 요청 개수를 제한.
만약 자식 프로세스가 이 값만큼의 클라이언트 요청을 받았다면 이 자식 프로세스는 자동으로 kill 됩니다.
(0 인 경우 무한대)
Worker
1) 자식 프로세스들이 각각 여러 쓰레드를 사용하며, 각 쓰레드는 한번에 한 연결을 담당
2) Worker 방식은 일반적으로 멀티 CPU 시스템에서 성능이 좋다
3) 요청을 쓰레드 단위로 처리 ( 최대 64개의 쓰레드 처리 가능 )
4) 지정된 만큼의 프로세스와 각 쓰레드를 준비하여 클라이언트의 요청을 받아들이는 설정
5) 기본 사용 메모리는 prefork보다 낮으며 쓰레드 간에 메모리를 서로 공유함
6) 동시접속자가 많은 사이트에 적합
<IfModule mpm_worker_module>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
l StartServers(Default 3)
시작시에 생성되는 서버 프로세스의 개수, 자식 프로세스의 수는 부하에 따라 동적으로 변경되기 때문에 이 값은 큰 의미가 없습니다.
l ServerLimit (default : 16)
구성 가능한 child 프로세스의 제한 수.
ServerLimit 값이 필요 이상 높게 설정 된다면, 불필요한 공유 메모리가 할당 되므로 적절한 설정 필요합니다.
MaxClient 와 ThreadPerChild 에서 요구한 프로세스 수보다 높게 설정하지 마시기 바랍니다.
l MaxClient (default : ServerLimit * ThreadsPerChild)
동시에 처리될 최대 커넥션(request)의 수
MaxClients 수치를 초과한 후 온 요청들은 ListenBackLog에 의해 큐잉됩니다.
ThreadsPerChild 옵션과 매우 긴밀하게 작용
동접자가 많을 경우, 이 MaxClient값을 증가시켜야 합니다.
OS의 FD(File Descriptor)값을 증가 시켜 MaxClient 의 상한값을 증가시키시기 바랍니다.
l MinSpareThreads(default 75)
최소 thread 개수
만약 서버에 idle 쓰레드가 충분하지 않다면 child 프로세스는 idle 쓰레드가 MinSpareThreads 보다 커질때까지 생성됩니다.
l MaxSpareThreads(default 250)
최대 thread개수
만약 서버에 너무 많은 idle 쓰레드가 존재하면 child 프로세스는 idle 쓰레드가 MaxSpareThreads 수보다 작아질 때까지 kill 됩니다.
l ThreadPerChild
개별 자식 프로세스가 지속적으로 가질 수 있는 Thread의 개수
l MaxRequestPerChild
자식 프로세스가 서비스할 수 있는 최대 요청 개수
l ThreadLimit (default : 64)
child 프로세스의 라이프주기 동안 ThreadsPerChild 의 최대 설정값을 설정합니다.
ThreadLimit 가 ThreadsPerChild 보다 훨씬 높게 설정된다면, 여분의 미사용 공유 메모리가 할당될 것입니다.
ThreadLimit 과 ThreadsPerChild 모두 시스템이 감당할 수 있는 값 보다 높게 설정하면,
아파치가 기동되지 않거나 시스템이 불안정하게 될 수 있습니다.
* 이 값은 최대 예상 ThreadsPerChild 의 설정보다 높게 설정하면 안됩니다.
Prefork 와 Worker 방식이 차이점
1) Worker가 Prefork에 비해 적은 메모리 사용한다.
2) Worker : 통신량이 많은 서버에 적절한 형태를 가진다.
3) Prefork : 안전하지 않은 제 3자가 만든 모듈을 사용할 수 있다.
4) Prefork : 디버깅이 빈약한 플랫폼에서 쉽게 디버깅 할 수 있다.
5) ‘Worker‘ 와 ‘Prefork‘ 의 속도는 비슷하다.
현재 worker 모듈 설치 되었는지 확인하는 방법
# httpd -V
Compiled using: APR 1.4.2, APR-Util 1.3.9
Architecture: 32-bit
Server MPM: Worker
threaded: yes (fixed thread count)
forked: yes (variable process count)
Server compiled with....
apache 2.4 event-mpm nginx-1.4 비교
nginx (http://nginx.org)
러시아인 igor sysoev가 2004년 처음 릴리즈한 웹서버.
nginx는 C10K problem을 해결하기 위하여 기존 아파치 방식 처럼 하나의 쓰레드에서 하나의 클라이언트 요청을 처리하는 것이 아닌 event-driven 구조를 사용한다.
최근 점유율이 빠르게 상승하고 있는 웹 서버.
아파치
KeepAlive
HTTP프로토콜상 한번 접속 후 자료를 모두 전송하면 접속을 끊어 버리지만 KeepAlive On 상태에서는 KeepAliveTimeOut시간 동안 접속을 끊지 않고 다음 접속을 기다린다.
순수 html파일, 이미지파일 등으로만 구성된 서버(동적파일이 없는서버)에 KeepAlive On으로 설정할 경우 50%정도의 성능 향상을 보인다고 한다. 단 이와 같은 성능향상을 보이려면 서버가 바쁘지 않아야 한다. 아주 바쁜 서버 환경에서 KeepAlive On을 설정해 놓을 경우 모든 접속자 마다 연결 유지를 해 놓아야 하기 때문에 아파치 프로세스수가 기하 급수적으로 늘어나 MaxClient값을 초과하게 된다. 또한 On상태일때 접속유지 하는 프로세스들 때문에
메모리를 그 만큼 많이 사용하게 된다. 따라서 KeepAlive값은 단순히 On/Off 시킬것이 아니라 접속자, 메모리용량과 연관해서 값을 설정하여야한다.
접속자가 많지만 메모리가 충분하다 : On
접속자가 많지만 메모리 여유가 없다 : Off
접속자가 적고 메모리가 충분하다 : On
접속자가 적고 메모리 여유가 없다 : Off
- 메모리가 충분하다는 의미는 접속자가 MaxClient값에 도달했을 경우라도 swap메모리를 사용하지 않는상태를 뜻한다.
httpd.conf 최대 동시접속수 : StartServers * ThreadsPerChild = 4 * 25 = 100 <IfModule worker.c> StartServers 4 MaxClients 400 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 4000 </IfModule> nginx.conf |
user nginx; worker_processes 1; error_log /var/log/nginx/error.log info; pid /var/run/nginx.pid;
# Events Module events { worker_connections 1024; }
[...]
http { include /etc/nginx/mime.types; default_type application/octet-stream; [...] sendfile on; tcp_nopush on; tcp_nodelay on; server_tokens off; keepalive_requests 100; keepalive_timeout 65 20; [...] |