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 | 방식 | 운영에서 보는 관점 |
|---|---|---|
event | process + thread + event 처리 | KeepAlive idle 연결을 더 효율적으로 다룸 |
worker | process + thread | 많은 요청을 적은 프로세스로 처리 |
prefork | process 기반 | 스레드 비호환 모듈이 있을 때 만남 |
현대 Linux 배포판에서는 event MPM을 자주 본다. 다만 오래된 서버, 특정 모듈, 패키지 기본값에 따라
worker나 prefork가 남아 있을 수 있으니 실제 로드된 MPM을 먼저 확인한다.
먼저 확인할 값
httpd -V
apachectl -M | grep mpm
apachectl configtest
httpd -V에서 Server MPM을 확인하고, apachectl -M에서 실제 로드된 mpm_*_module을 본다.
MPM은 동시에 여러 개를 켜는 개념이 아니므로 어떤 MPM이 올라왔는지가 출발점이다.
worker 수 계산
| 지시어 | 보는 이유 |
|---|---|
MaxRequestWorkers | 동시에 처리할 수 있는 요청 수의 상한 |
ServerLimit | 생성 가능한 child process 상한 |
ThreadsPerChild | child process 하나가 가진 thread 수 |
StartServers | 시작 시 띄울 child process 수 |
MinSpareThreads / MaxSpareThreads | idle thread 유지 범위 |
MaxConnectionsPerChild | child process가 처리한 연결 수가 넘으면 재시작 |
event와 worker 계열에서는 대략 다음 관계로 감을 잡는다.
MaxRequestWorkers ~= ServerLimit * ThreadsPerChild
설정값을 올릴 때는 Apache만 보지 않는다. 뒤쪽 Tomcat의 maxThreads, DB connection pool, 외부 API 처리량까지
같이 봐야 한다. 앞단 worker만 크게 늘리면 장애가 사라지는 것이 아니라 뒤쪽 병목이 더 빨리 드러난다.
KeepAlive 설정
| 지시어 | 의미 | 운영 메모 |
|---|---|---|
KeepAlive | persistent connection 사용 여부 | 보통 On |
MaxKeepAliveRequests | 한 연결에서 허용할 요청 수 | 너무 낮으면 재연결 증가 |
KeepAliveTimeout | 다음 요청을 기다리는 시간 | 높으면 idle 연결이 오래 남음 |
TimeOut | Apache I/O 기본 timeout | proxy timeout의 기본값이 될 수 있음 |
ProxyTimeout | proxy 요청 timeout | mod_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 지연 |
| 간헐적 503 | worker 여유, backend health, maintenance |
| idle connection이 많음 | KeepAliveTimeout, client 패턴 |
| Apache 메모리 증가 | MPM 종류, child process 수, MaxConnectionsPerChild |
| 설정 변경 후 기동 실패 | MPM 중복 로드, ServerLimit/MaxRequestWorkers 관계 |
가능하면 mod_status를 제한된 내부망에서만 열어 busy worker와 idle worker를 같이 본다.
단, 상태 페이지는 서버 내부 정보가 보이므로 외부에 노출하지 않는다.
관련 문서
공식 문서
- Apache MPM Common Directives
- Apache MPM event
- Apache MPM worker
- Apache MPM prefork
- Apache Core KeepAlive
- Apache Core KeepAliveTimeout
닫기 전 질문
- 현재 서버의 MPM은
event,worker,prefork중 무엇인가? MaxRequestWorkers는 TomcatmaxThreads와 비교해 과하지 않은가?KeepAliveTimeout은 트래픽 패턴에 비해 너무 길지 않은가?- worker 부족인지, backend 지연인지 로그와 상태 지표로 구분했는가?