본문 바로가기

카테고리 없음

(펌) prefork to worker MPM

http://egloos.zum.com/js7309/v/11095230

 

[CENTOS] apache web server switching from prefork to worker MPM

Switching Apache from Prefork to Worker MPM(Multi-Processing Modules; 다중처리모듈)아파치 설치시 mpm 모드는 prefork, worker, winnt, netware, beos 등을 지원한다, prefork 프로세스를 제어하는 부모 프로세스는 미리 생성해서 만들어 놓은 자식 프로세스(S

egloos.zum.com

 

Switching Apache from Prefork to Worker MPM(Multi-Processing Modules; 다중처리모듈)


아파치 설치시 mpm 모드는 prefork, worker, winnt, netware, beos 등을 지원한다,

  prefork

       프로세스를 제어하는 부모 프로세스는 미리 생성해서 만들어 놓은 자식 프로세스(StartServers에서 정의)를 
       대기시키고 있다가 클라이언트 요청이 들어올 경우 
       자신을 자식 프로세스로 복제(메모리 영역까지 같이) 시켜 실행한다. 
        즉, 하나의 프로세스는 하나의 독립된 쓰레드를 가지고 실행한다.
       또한 다른 디버깅 하기 힘든 인터프리터한 언어로 작성된 어플리케이션을 직접 구동할 경우 
       쉬운 디버깅 기능을 제공한다. 
       때문에 PHP 같은 언어로 구동할 때 유리하다는 장점이 있다. 
       단, 프로세스가 메모리를 직접 공유하지 않으므로 메모리 공간이 독립적이라 안정성은 있으나,
       통신량이 많은 서버일 경우 그만큼 복제 되는 메모리수가 증가 하므로  프로세스의 소비하는 메모리량이 
       많아 질 수 밖에 없다.
   

  worker
      prefork 와 다른게 부모 프로세스는 쓰레드를 가지지 않고, 
      미리 설정된 자식프로세스를 여러개(StartServers에서 정의) 생성해 놓고 있다가.
      요청이 들어 오면, 그 자식 프로세스가 가지고 있는 여러개의 worker Thread를 가지고 처리 하는 방식이며,  
      (자식 프로세스 당 최대 64개의 쓰레드)  
      각 쓰레드는 한번에 하나의 연결을 담당하기 때문에 통신량이 많은 서비스에 적당하다.
      또한 쓰레드는 메모리를 공유 하므로 prefork 보다 메모리 사용량이 적다. 하지만 여러개의 쓰레드가 
      응용 리소스(php같은)를 동시에 처리 할 경우
      이상이 생기면 오류가 생긴 메모리르 공유하던 모든 쓰레드에서 오동작을 일으킬 수 있으므로 
      응용모듈을 같이 사용하는 것을 제한한다.
      만약 php를 사용 하고 싶다면  FastCGI(mod_fcgid.so) 모듈을 따로 설치 해, 설정 해주워야 한다.
       (http://www.fastcgi.com/drupal/)
      주로 proxy, rewriteURL, static resource(css, js, image 같은) 목적으로 사용 시 사용하면 좋다.



일반적으로 설정을 하지 않는다면, 리눅스의 경우 prefork 모드로 설치 된다.

그래서 설치 시 반드시 ./configure  옵션에 --with-mpm=worker 명시하고 설치한다.

해당 아파치가 어떤 모듈로 설치 되었는지 보는 방법은 컴파일된 모듈을 보는

httpd -l

명령어를 실행하거나,

Compiled in modules:
  core.c
  worker.c
  http_core.c
  mod_so.c

아니면 해당 아파치의 컴파일 옵션을 보는 방법이 있다.

httpd -V

명령어를 실행하면,

Server version: Apache/2.2.24 (Unix)
Server built:   Feb 12 2012 17:44:41
Server's Module Magic Number: 20051115:31
Server loaded:  APR 1.4.6, APR-Util 1.4.1
Compiled using: APR 1.4.6, APR-Util 1.4.1
Architecture:   64-bit
Server MPM:     Worker
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)

Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/worker"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/apache24"
 -D SUEXEC_BIN="/apache24/bin/suexec"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

위 두 명령어에 실행된 정보에서 보든 worker.c  나 Server MPM: Worker 에서 처럼
worker 모드로 설정를 확인 한다. 

만약 worker로 설정 되어 있지 않다면, "httpd -l" 명령이 시

  core.c
  prefork.c
  http_core.c
  mod_so.c

혹은 "httpd -V" 시

Architecture:   64-bit
Server MPM:     Prefork
  threaded:     no

를 확인 할 수 있다.

우분투 경우

sudo apt-get install apache2-mpm-worker

따로 설치 해야 하는 경우도 있지만, 센토스의 경우,

vi /etc/sysconfig/httpd

로 해당 파일을 열어 #HTTPD=/usr/sbin/httpd.worker 옵션에 주석(#)을 풀어 주고 restart 하면 된다.
/usr/sbin/httpd.worker -k restart
반대로 worker 에서 prefork 로 변경 할 경우 주석을 막고 restart를 하면 된다.

# Configuration file for the httpd service.

#
# The default processing model (MPM) is the process-based
# 'prefork' model.  A thread-based model, 'worker', is also
# available, but does not work with some modules (such as PHP).
# The service must be stopped before changing this variable.
#
#HTTPD=/usr/sbin/httpd.worker

#
# To pass additional options (for instance, -D definitions) to the
# httpd binary at startup, set OPTIONS here.
#
#OPTIONS=

#
# By default, the httpd process is started in the C locale; to
# change the locale in which the server runs, the HTTPD_LANG
# variable can be set.
#
#HTTPD_LANG=C

#
# By default, the httpd process will create the file
# /var/run/httpd/httpd.pid in which it records its process
# identification number when it starts.  If an alternate location is
# specified in httpd.conf (via the PidFile directive), the new
# location needs to be reported in the PIDFILE.
#
#PIDFILE=/var/run/httpd/httpd.pid

또한,
httpd.conf 파일을 열어 
#Include conf/extra/httpd-mpm.conf
항목에 대한 주석(#)을 제거 한다.

그리고 httpd-mpm.conf 항목을 열어  mpm_worker_module 옵션을 자신에 맞는 시스템에 맞게 수정해야 한다.

<IfModule mpm_worker_module>
    ServerLimit    16 
    StartServers      16 
    MaxClients       150  
    MinSpareThreads   25
    MaxSpareThreads   75 
    ThreadsPerChild   25
    MaxRequestsPerChild 0 
</IfModule>

* 프로세스 개수
- Active Child Process의 최대 개수는 MaxClients 값과 ThreadsPerChild 값의 의해서 계산된다.
- 만약, MaxClients를 4096으로 하고, ThreadPerChild를 128로 하면
   MaxClients(4096) / ThreadPerChild(128) = 32 
   따라서 32개의 프로세스가 생성된다.
- 이 수치를 변경할 경우 Apache를 완전히 재시작 해야 함.
- prefork 방식일 때의 connection pool은 
   MaxClients  : Tomcat maxThreads 값 * load balanced 개수 (연동되는 was instance 개수; worker 갯수) 
                        = Apache Http MaxClients 
- worker 방식일 때의 connection pool은 (MaxClients / ThreadsPerChild) * connection _pool_size 
 
ServerLimit (default : 16)
- 구성 가능한 child 프로세스의 제한 수.
- 이 ServerLimit 값이 필요 이상 높게 설정 된다면, 쓸데 없이 미사용 공유 메모리가 할당 되므로 적절하게 설정 필요.
- MaxClient 와 ThreadPerChild 에서 요구한 프로세스 수 보다 높게 설정하지 말 것.
 
StartServers (default : 3)
- Apache기동시에 띄울 프로세스 개수

- 자식 프로세스의 수는 부하에 따라 동적으로 변경되기 때문에 이 설정은 큰 의미가 없다.
 
MaxClient (default : ServerLimit x ThreadsPerChild)
- 동시에 처리될 최대 커넥션(request)의 수
- MaxClients 수치를 초과한 후 온 요청들은 ListenBackLog에 의해 큐잉됨
- ThreadsPerChild 옵션과 매우 긴밀하게 작용함
- OS의 FD(File Descriptor)값을 증가 시켜 MaxClient 의 상한값을 증가시키도록 할 것.
- 동접자가 많을 경우, 이 MaxClient값을 증가시키되, 
   최대 값만큼 httpd 프로세스가 생성되더라도 시스템 전체 메모리 사용률이 80%가 넘지 않도록 설정.
- top의 httpd 프로세스에 대한 RES 기준으로 설정
  예를 들어 httpd 프로세스인 4m 라고 가정하고 100개의 MaxClients를 설정했다면
  최소 400m+a 정도의 메모리가 필요하게 된다.

 
MinSpareThreads (default : 75)
- Request spike를 처리할 최소 idle 쓰레드 수 
- 만약 서버에 idle 쓰레드가 충분하지 않다면 child 프로세스는 idle 쓰레드가 MinSpareThreads 보다 커질때까지 생성된다.
     
MaxSpareThreads (default : 250)
- Idle 쓰레드의 최대 수 
- 만약 서버에 너무 많은 idle 쓰레드가 존재하면 child 프로세스는 idle 쓰레드가 MaxSpareThreads 수 보다 
   작아질 때까지 죽는다.
     
ThreadsPerChild (default : 64)
- 각 child 프로세스가 생성한 쓰레드 수 
- Child 프로세스는 기동시 ThreadsPerChild 개수만큼 쓰레드를 생성하고 결코 더 이상 생성하지 않는다. 
- 만약 worker 방식의 MPM을 사용중이라면, 전체 쓰레드 수는 평상시 부하를 처리할 만큼 충분히 많아야만 한다.
     
MaxRequestsPerChild
- 각 각의 child 프로세스가 처리할 request의 수를 제한. 
- MaxRequestsPerChild 개수를 처리한 후, child 프로세스는 종료(die)된다. 
- 0으로 설정하면 무한대
- MaxRequestsPerChild 를 0 이외의 값으로 설정하는 것은 프로세스가 (혹시나) 메모리 누수로 사용할 수 있는 
  메모리 양을 제한한다.
 
ThreadLimit (default : 64)
- child 프로세스의 라이프주기 동안 ThreadsPerChild 의 최대 설정값을 설정한다.

- 이 지시자를 사용할 때는 특별한 주의가 필요하다. 
- ThreadLimit 가 ThreadsPerChild 보다 훨씬 높게 설정된다면, 여분의 미사용 공유 메모리가 할당될 것이다.
- ThreadLimit 과 ThreadsPerChild 모두 시스템이 다룰 수 있는 것 보다 높게 설정한다면, 
   아파치가 기동되지 않거나 시스템이 불안정하게 될 수 있다. 
- 이 지시자를 당신의 최대 예상 ThreadsPerChild 의 설정보다 높게 설정하지 않도록 한다.
  

 

KeepAlive 설정.


KeepAlive 는 HTTP 1.1 규약에서부터 적용된 것으로 접속 속도에 큰 영향을 준다.
HTTP/1.1 부터 Keep Alive connection(persistent connection) 를 지원 하며 
KeepAlive On 설정시 response header에  "Transfer-Encoding: chunked" 정보를 보냄으로써 
클라이어트로 부터 지속적인 연결을 지시 할 수 있다. 
반면 HTTP/1.0 경우 Content Length에 서버에서 보낼 정확한 콘텐츠 길이를 명시 하므로 클라이언트가 해당 리소스를
다 전송받으면 연결이 끊어지게 된다.
 
KeepAlive 를 Off 로 설정시 다소 접속 속도는 떨어지지만 좀 더 많은 동시 접속을 수용할 수 있다. 
따라서 MaxClients 에 도달할 정도로 동시 접속자가 많은 경우에는 KeepAlive 를 Off 로 설정하는 것이 다소 임시 방편이기는 
하지만 해결 방법은 아니다.

한가지 예를 들어 하나의 웹페이지는 여러개의 링크(src, link href)로 구성되 정보를 읽어 드려 클라이언트에서 파싱된다.
웹페이지 안에는 css 라던지 js, image 같은 각종 static resource 파일이 추가적으로 웹서버에게 리소스를 요청한다.
이때, KeepAlive가 On 인경우 클라이언트로 부터 요청된 TCP 연결에 대해 같은 IP로 추가 적인 요청이 있을거라는 예상하고
KeepAliveTimeOut에 명시된 시간만큼 연결을 끊지 않고 대기 하고 있다가 요청이 들어 오면 연결 세션을 맺는 절차 
없이 바로 연결하여 데이터를 전송하여 실제 클라언트 사용자가 보다 빠른 웹페이지를 랜더링 할 수 있다.
KeepAlive가 Off 경우 매번 새로운 연결 세션을 만들어 처리 하기 때문에 속도가 느려질 수 밖에 없다.
만약 이미지 파일이 많은 HTML 문서를 로딩시 KeepAlive 설정에 따라 최고 50%까지 속도 차이가 날 수 있다고 한다.
이미지나 추가적인 웹리소스를 페이지 내에서 호출하는 정도가 빈약하다면  KeepAlive 를 Off 로 하는 것이 유리하다.
KeepAlive 를 On으로 설정하여 그대로 사용할 경우에는 15초 정도로 설정된 KeepAlive Timeout (default: 15초)을 
5초 정도로 짧게 설정하는 방법도 있다. 
KeepAlive는 클리언트에 연결 세션에 영향을 많이 줌으로 설정시 시스템 메모리의 용량에도 많은 영향이 있다.
또한  MPM의 설정이나 타잎에 대해서도 밀접한 관계가 있다. 시스템에 접속자 그리 많이 않고 메모리용량도
충분하다면 당연히 On으로 하는 것도 좋겠지만, 메모리용량 넉넉치 않다면 Off로 하는 것도 시스템 장애를 미연에
막는 대처일 수도 있다.