Apache MPM과 KeepAlive

Apache HTTP Server의 MPM, worker 수, KeepAlive, timeout 설정을 운영 관점에서 정리한다.


MPM과 KeepAlive가 보는 구간

Client
  -> Apache HTTP Server
     -> MPM process/thread
     -> KeepAlive connection
  -> WAS / Application

MPM(Multi-Processing Module)은 Apache HTTP Server가 요청을 처리할 프로세스와 스레드를 어떻게 만들지 정하는 실행 모델이다. KeepAlive는 하나의 TCP 연결에서 여러 HTTP 요청을 이어서 처리하도록 유지하는 기능이다.

둘은 함께 봐야 한다. KeepAlive 연결이 오래 유지되면 클라이언트 입장에서는 재연결 비용이 줄지만, 서버 입장에서는 worker나 연결 슬롯이 idle 상태로 오래 묶일 수 있다.

Apache HTTP Server의 worker는 사용자 로그인 세션을 의미하지 않는다. 여기서 worker는 요청이나 연결을 처리하는 process/thread이고, 세션은 보통 Tomcat이나 애플리케이션 계층에서 관리하는 사용자 상태다.

MPM 종류

MPM방식운영에서 보는 관점
eventprocess + thread + event 처리KeepAlive idle 연결을 더 효율적으로 다룸
workerprocess + thread많은 요청을 적은 프로세스로 처리
preforkprocess 기반스레드 비호환 모듈이 있을 때 만남

현대 Linux 배포판에서는 event MPM을 자주 본다. 다만 오래된 서버, 특정 모듈, 패키지 기본값에 따라 workerprefork가 남아 있을 수 있으니 실제 로드된 MPM을 먼저 확인한다.

먼저 확인할 값

httpd -V
apachectl -M | grep mpm
apachectl configtest

httpd -V에서 Server MPM을 확인하고, apachectl -M에서 실제 로드된 mpm_*_module을 본다. MPM은 동시에 여러 개를 켜는 개념이 아니므로 어떤 MPM이 올라왔는지가 출발점이다.

worker 수 계산

지시어보는 이유
MaxRequestWorkers동시에 처리할 수 있는 요청 수의 상한
ServerLimit생성 가능한 child process 상한
ThreadsPerChildchild process 하나가 가진 thread 수
StartServers시작 시 띄울 child process 수
MinSpareThreads / MaxSpareThreadsidle thread 유지 범위
MaxConnectionsPerChildchild process가 처리한 연결 수가 넘으면 재시작

eventworker 계열에서는 대략 다음 관계로 감을 잡는다.

MaxRequestWorkers ~= ServerLimit * ThreadsPerChild

설정값을 올릴 때는 Apache만 보지 않는다. 뒤쪽 Tomcat의 maxThreads, DB connection pool, 외부 API 처리량까지 같이 봐야 한다. 앞단 worker만 크게 늘리면 장애가 사라지는 것이 아니라 뒤쪽 병목이 더 빨리 드러난다.

KeepAlive 설정

지시어의미운영 메모
KeepAlivepersistent connection 사용 여부보통 On
MaxKeepAliveRequests한 연결에서 허용할 요청 수너무 낮으면 재연결 증가
KeepAliveTimeout다음 요청을 기다리는 시간높으면 idle 연결이 오래 남음
TimeOutApache I/O 기본 timeoutproxy timeout의 기본값이 될 수 있음
ProxyTimeoutproxy 요청 timeoutmod_proxy 연동에서 별도 확인

KeepAliveTimeout은 크게 잡는다고 항상 좋은 값이 아니다. 트래픽이 많은 서버에서 너무 길면 idle client를 기다리는 연결이 늘고, worker 여유가 줄어든다.

설정 예시

LoadModule mpm_event_module modules/mod_mpm_event.so

<IfModule mpm_event_module>
    ServerLimit 16
    StartServers 4
    ThreadsPerChild 25
    MaxRequestWorkers 400
    MinSpareThreads 75
    MaxSpareThreads 250
    MaxConnectionsPerChild 10000
</IfModule>

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
TimeOut 60

이 값은 예시일 뿐이다. 운영에서는 CPU, 메모리, 평균 응답 시간, Tomcat thread, DB pool을 보고 조정한다.

증상별 확인

증상확인 지점
접속은 되지만 응답이 느림busy worker, Tomcat thread, DB 지연
간헐적 503worker 여유, backend health, maintenance
idle connection이 많음KeepAliveTimeout, client 패턴
Apache 메모리 증가MPM 종류, child process 수, MaxConnectionsPerChild
설정 변경 후 기동 실패MPM 중복 로드, ServerLimit/MaxRequestWorkers 관계

가능하면 mod_status를 제한된 내부망에서만 열어 busy worker와 idle worker를 같이 본다. 단, 상태 페이지는 서버 내부 정보가 보이므로 외부에 노출하지 않는다.

관련 문서

공식 문서

닫기 전 질문

  • 현재 서버의 MPM은 event, worker, prefork 중 무엇인가?
  • MaxRequestWorkers는 Tomcat maxThreads와 비교해 과하지 않은가?
  • KeepAliveTimeout은 트래픽 패턴에 비해 너무 길지 않은가?
  • worker 부족인지, backend 지연인지 로그와 상태 지표로 구분했는가?