아무거나

아파치 서버 MPM, worker, prefork 방식 본문

IT/Apache

아파치 서버 MPM, worker, prefork 방식

bkjeon1614 전봉근 2018. 7. 11. 00:52

1. 아파치 서버 MPM( Apache Multi-Processing Modules )

    - 아파치 서버가 클라이언트에게서 받아들인 요청을 처리하기 위하여 자식 프로세스들에게 분배하는 모듈

    - prefork 방식과 worker 방식이 있다


2. prefork

    - 하나의 자식 프로세스가 하나의 스레드를 갖는 구조로, 자식 프로세스는 최대 1024개까지 가능하다.

    - 스레드 간 메모리 공유 안 함(독립적이라 안정적인 대신에 메모리를 많이 사용)

    - 실행 중인 프로세스 복제하여 실행(메모리 영역까지 같이 복제)

    - 응답 프로세스를 미리 띄워놓고 클라이언트 요청 시 자식 프로세스가 반응하게 되는 방식

    - 디버깅이 빈약한 플랫폼에서 쉬운 디버깅 가능

    - 안전하지 않는 제3자가 만든 모듈 사용 가능

    - 일반적으로 single CPU 또는 Dual CPU에서 성능이 좋음


3. worker

    - prefork보다 메모리 사용량 적음. 통신량이 많은 서버에 적절하다(=동시접속자가 많은 사이트에 적합)

    - 프로세스당 스레드(연결) 여러 개이며 최대 64개의 스레드 처리가 가능하다. -> 즉, 자식 프로세스들이 각각 여러 스레드를 사용하며, 각 스레드는 한번에 한 연결을 담당한다 

    - 스레드간에 메모리를 공유한다

    - worker 방식은 일반적으로 멀티 CPU 시스템에서 성능이 좋다


4. prefork vs worker

 prefork

 worker

 안전하지 않는 제 3자가 만든 모듈을 사용할 수 있다.

 통신량이 많은 서버에서 적절한 형태를 가진다.

 디버깅이 빈약한 플랫폼에서 쉽게 디버깅 할 수 있다.

 prefork에 비해 적은 메모리를 사용한다.

 prefork와 worker의 속도는 비슷하다.


5. event

    - Nginx는 Event Driven 방식의 웹 서버로 유명하다. 하지만 Apache는 그동안에 Event Driven 방식을 지원하지 않았다. 대신 한 개의 동접 클라이언트당 한 개의 스레드(or 프로세스) 구조였고 이 때문에 한 클라이언트가 맺은 접속이 완전히 끝나지 않는 한 스레드 혹은 프로세스가 죽지 않는 방법을 사용했다.(=Keep Alive) 그러므로 대량 접속에서는 효율이 급격하게 떨어지는 문제점도 안고 있었다. 이러한 문제를 해결하기 위해 Apache 2.4부터는 Event MPM을 사용할 수 있게 되었다. Event MPM을 사용하기 위해서는 Kqueue나 Epoll 과 호환되는 시스템이 필요하다.


6. history

   (1) apache(2.2) > nginx : 고용량의 정적 파일 및 큰 규모의 사이트가 많아짐에 따라 대량 접속에도 적은 리소스를 사용하면서 빠르게 서비스할 수 있는 웹 사이트가 유명해지면서 그에 적합한 nginx를 선호하게 되었다.

   (2) apache(2.4) vs nginx : Apache에서도 빠른 응답속도와 적은 리소스 등 기존과 다르게 큰 변화를 주어 2012년 2월 달쯤에 2.4버전을 릴리즈 하였다.

   (3) apache 2.2 : 동접자수가 많거나 확장성이 필요한 사이트는 worker 방식을 택하고, 안정성과 오래된 소프트웨어와 호환성이 필요한 사이트는 prefork를 보편적으로 사용한다. Linux의 경우 prefork 방식이 기본 설정이다. prefork 방식은 하나의 자식 프로세스가 하나의 스레드를 갖는 구조이며 즉, 한 클라이언트가 맺은 접속이 완전히 끝나지 않는 한 스레드(or 프로세스)가 죽지 않는다. 때문에 접속당 CPU와 메모리 사용이 증가하여 성능 저하 발생

       * keepalive 설정 -> 대량접속시 효율적 문제

   (4) apache 2.4 : event방식을 지원하며 event방식은 요청과 Keep Alive한 아파치 요청을 그대로 맺는 것이 아니라, 요청을 처리하는 스레드를 따로 두도록 하여 분산된 처리방식

       

6. 설정 방법 (2.4.x 기준) : 해당 ex는 prefork에서 worker로 변경하는 내용을 기술했다.

    (1) 현재 아파치 정보 확인

# apachectl -V
Server version: Apache/2.4.18 (Ubuntu)
Server built:   2018-04-18T14:53:04
Server's Module Magic Number: 20120211:52
Server loaded:  APR 1.5.2, APR-UTIL 1.5.4
Compiled using: APR 1.5.2, APR-UTIL 1.5.4
Architecture:   32-bit
Server MPM:     prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -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=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

    (2) 아파치가 사용중인 MPM 모듈 확인

# apachectl -V | grep -i mpm
Server MPM:     prefork

    (3) 현재 사용가능한 MPM 모듈 확인

# ls -l /etc/apache2/mods-available/mpm*
-rwxr-x--- 1 dev dev 668 Mar 19  2016 /etc/apache2/mods-available/mpm_event.conf
-rwxr-x--- 1 dev dev 106 Mar 19  2016 /etc/apache2/mods-available/mpm_event.load
-rwxr-x--- 1 dev dev 571 Mar 19  2016 /etc/apache2/mods-available/mpm_prefork.conf
-rwxr-x--- 1 dev dev 108 Mar 19  2016 /etc/apache2/mods-available/mpm_prefork.load
-rwxr-x--- 1 dev dev 836 Mar 19  2016 /etc/apache2/mods-available/mpm_worker.conf
-rwxr-x--- 1 dev dev 107 Mar 19  2016 /etc/apache2/mods-available/mpm_worker.load

    (4) 현재 사용중으로 설정된 MPM 모듈 확인

# ls -l /etc/apache2/mods-enabled/mpm*
lrwxrwxrwx 1 root root 34 Jul 11 00:07 /etc/apache2/mods-enabled/mpm_prefork.conf -> ../mods-available/mpm_prefork.conf
lrwxrwxrwx 1 root root 34 Jul 11 00:07 /etc/apache2/mods-enabled/mpm_prefork.load -> ../mods-available/mpm_prefork.load

    (5) 현재 사용 중인 prefork 모듈을 사용안 함으로 설정

# a2dismod mpm_prefork
Module mpm_prefork disabled.
To activate the new configuration, you need to run:
  service apache2 restart

    (6) worker 모듈을 사용함으로 설정

# a2enmod mpm_worker
Enabling module mpm_worker.
To activate the new configuration, you need to run:
  service apache2 restart

    (7) 아파치 재시작

# service apache2 restart

    (8) 현재 MPM 모듈 확인

# apachectl -V | grep -i mpm
Server MPM:     worker

    (9) 기타

         - 만약 worker나 event 설정시에 오류가 발생했을 경우

[Wed Jul 11 00:20:29.961693 2018] [:crit] [pid 1055:tid 3074410240] Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe.  You need to recompile PHP.

            * 만약 PHP를 사용한다면 이런 오류를 표시하는 경우가 있다. 해당 오류는 PHP가 threadsafe를 지원하지 않아서 오류가 생기는 것이다. 그러므로 threadsafe에 대한 포스팅을 직접 찾아서 설정해주면 된다.


7. 모듈 내용 설명

    (1) worker

          

        StartServers : 아파치 시작시 생성되는 기본 프로세스 개수

        ServerLimit : 최대 실행가능한 프로세스 개수

        MaxClients : 최대동시접속자수

        MinSpareThreads : 최소로 유지할 쓰레드 개수

        MaxSpareThreads : 최대로 유지할 쓰레드 개수

        ThreadsPerChild : 하나의 자식프로세스가 가질 수 있는 쓰레드 개수

        MaxRequestsPerChild : 자식프로세스가 살아있는동안 요청을 받을 개수 

        MaxRequestWorkers : 동시에 처리할 수 있는 최대 연결 수(기본적으로는 256까지 사용가능하며, 컴파일 전에 파일을 수정(./server/mpm/prefork/prefork.c)하면 1024까지 올릴 수 있습니다.)

        MaxConnectionsPerChild : 서버 프로세스가 종료되기 전에 제공되는 최대 연결 수입니다. 0의 경우 제한이 없다라는 의미입니다.


    (2) prefork

         

        StartServers : 아파치 시작시 생성되는 기본 프로세스 개수

        MinSpareServers : 최소 프로세스의 개수

        MaxSpareServers : 최대 프로세스의 개수

        MaxClients : 아파치 시작시 최대로 실행할 자식프로세스의 개수

        MaxRequestWorkers : 동시에 처리할 수 있는 최대 연결 수(기본적으로는 256까지 사용가능하며, 컴파일 전에 파일을 수정(./server/mpm/prefork/prefork.c)하면 1024까지 올릴 수 있습니다.)

        MaxConnectionsPerChild : 서버 프로세스가 종료되기 전에 제공되는 최대 연결 수입니다. 0의 경우 제한이 없다라는 의미입니다.


    (3) event

         

        StartServers : 아파치 시작시 생성되는 기본 프로세스 개수

        MinSpareThreads : 최소로 유지할 쓰레드 개수

        MaxSpareThreads : 최대로 유지할 쓰레드 개수

        ThreadLimit : 최대 실행가능한 쓰레드 개수

        ThreadsPerChild : 하나의 자식프로세스가 가질 수 있는 쓰레드 개수

        MaxRequestWorkers : 동시에 처리할 수 있는 최대 연결 수(기본적으로는 256까지 사용가능하며, 컴파일 전에 파일을 수정(./server/mpm/prefork/prefork.c)하면 1024까지 올릴 수 있습니다.)

        MaxConnectionsPerChild : 서버 프로세스가 종료되기 전에 제공되는 최대 연결 수입니다. 0의 경우 제한이 없다라는 의미입니다.



8. 결론

    * 성능 테스트를 하면 nginx가 더 나은 성능을 보이지만 php를 사용한다는 가정하에 php 모듈을 직접 적재하여 운용할 수 있는 apache가 구조상 이점이 있기에 복잡한 구성의 웹 사이트 운영에서는 보다 적합할 수 있다. 실제로 여러 테스트 사례들도 apache event-mpm과 nginx 테스트 결과 큰 편차를 보이지 않고 있다는 점 등을 미루어 보아 전적으로 어느 한쪽이 좋다고 단정할 수 없다. 즉, 케이스별로 어떤 상황에서 어떻게 적용하느냐에 따라 다르기 때문이다.    


2 Comments
댓글쓰기 폼