Worker 프로세스·스레드 튜닝: Nginx와 Apache 최적화
Nginx와 Apache의 worker 설정은 서버 자원을 얼마나 효율적으로 사용할지 결정합니다. CPU 코어 수, 메모리, 요청 특성에 맞게 조정하면 처리량을 크게 높일 수 있습니다.
Nginx Worker 아키텍처
Nginx는 비동기 이벤트 기반 아키텍처를 사용합니다. 각 worker 프로세스가 수천 개의 연결을 동시에 처리할 수 있어 스레드 기반인 Apache보다 메모리 효율이 높습니다.
┌─────────────────────────────┐
클라이언트 연결 │ Master Process (root) │
────────────────▶ │ config reload, worker 관리 │
└──────────┬──────────────────┘
│ fork
┌────────────────┼────────────────┐
▼ ▼ ▼
Worker #1 Worker #2 Worker #3
(1 CPU core) (1 CPU core) (1 CPU core)
비동기 I/O 비동기 I/O 비동기 I/O
10,000+ 연결 10,000+ 연결 10,000+ 연결
Nginx worker 설정
# /etc/nginx/nginx.conf
# worker 프로세스 수: auto = CPU 코어 수만큼 자동 생성 (권장)
worker_processes auto;
# 특정 CPU에 worker 고정 (NUMA 아키텍처에서 L3 캐시 효율 향상)
# worker_cpu_affinity auto; # Nginx 1.9.10+
# worker당 최대 열린 파일 수 (OS 제한과 맞춤)
worker_rlimit_nofile 65535;
events {
# worker당 최대 동시 연결 수
# worker_processes × worker_connections = 최대 동시 클라이언트 수
worker_connections 4096;
# 이벤트 처리 방식: Linux는 epoll이 최적
use epoll;
# accept_mutex: 단일 worker가 accept 처리 (false = 모든 worker가 경쟁)
# 고트래픽: off (성능 향상), 저트래픽: on (CPU 절약)
accept_mutex off;
# 한 번에 여러 연결 수락
multi_accept on;
}
OS 파일 디스크립터 한도 설정
# 현재 한도 확인
ulimit -n # 소프트 한도
ulimit -Hn # 하드 한도
# /etc/security/limits.conf 에 추가
nginx soft nofile 65535
nginx hard nofile 65535
* soft nofile 65535
* hard nofile 65535
# systemd 서비스라면 /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitNOFILE=65535
sudo systemctl daemon-reload
sudo systemctl restart nginx
# /proc/sys/fs/file-max: 시스템 전체 파일 디스크립터 한도
echo 2097152 | sudo tee /proc/sys/fs/file-max
echo "fs.file-max = 2097152" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Apache MPM 선택과 설정
Apache는 Multi-Processing Module(MPM)에 따라 요청 처리 방식이 다릅니다.
| MPM | 방식 | 특징 | HTTP/2 |
|---|---|---|---|
| Prefork | 프로세스 | PHP mod_php 호환, 메모리 多 | ❌ |
| Worker | 스레드 | 메모리 효율, PHP 불안정 | 제한적 |
| Event | 비동기 스레드 | Keep-Alive 효율, 권장 | ✅ |
# MPM 변경 (Prefork → Event)
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo systemctl restart apache2
# PHP 사용 시: mod_php → php-fpm으로 전환 필요
sudo a2dismod php8.1
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.1-fpm
MPM Event 튜닝
# /etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
# 시작 시 생성할 서버 프로세스 수
StartServers 2
# 최소/최대 유휴 스레드 수
MinSpareThreads 25
MaxSpareThreads 75
# 프로세스당 스레드 수 (MaxRequestWorkers / ServerLimit)
ThreadsPerChild 25
# 전체 최대 요청 처리 스레드
# MaxRequestWorkers = ServerLimit × ThreadsPerChild
MaxRequestWorkers 400
# 최대 프로세스 수
ServerLimit 16
# 프로세스당 최대 요청 수 (이후 재생성)
MaxConnectionsPerChild 10000
# Keep-Alive 비동기 처리 스레드
AsyncRequestWorkerFactor 2
</IfModule>
서버 규모별 권장 설정
소형 서버 (2 CPU, 4GB RAM)
# Nginx
worker_processes 2;
worker_connections 2048;
# Apache MPM Event
MaxRequestWorkers 150
ThreadsPerChild 25
ServerLimit 6
중형 서버 (8 CPU, 16GB RAM)
# Nginx
worker_processes auto; # 8
worker_connections 4096;
# Apache MPM Event
MaxRequestWorkers 400
ThreadsPerChild 25
ServerLimit 16
대형 서버 (32 CPU, 64GB RAM)
# Nginx
worker_processes auto; # 32
worker_connections 16384;
worker_rlimit_nofile 65535;
# Apache MPM Event
MaxRequestWorkers 2000
ThreadsPerChild 50
ServerLimit 40
Worker 상태 모니터링
# Nginx status 페이지 활성화
server {
listen 127.0.0.1:8080;
location /nginx_status {
stub_status on;
access_log off;
}
}
curl http://127.0.0.1:8080/nginx_status
# Active connections: 150
# server accepts handled requests
# 1234567 1234567 3456789
# Reading: 3 Writing: 12 Waiting: 135
# ─────────────────────────────────────
# Waiting: 유휴 keepalive 연결 수
# Writing: 현재 응답 전송 중인 연결 수
# Reading: 요청 헤더 읽는 중인 연결 수
# Apache status 페이지
sudo a2enmod status
# /etc/apache2/conf-available/server-status.conf
<Location "/server-status">
SetHandler server-status
Require ip 127.0.0.1
</Location>
curl http://127.0.0.1/server-status?auto
# BusyWorkers: 25
# IdleWorkers: 175
# Scoreboard: ....W.W.....K......
프로세스 수 계산식
Nginx 최대 동시 처리 수:
= worker_processes × worker_connections
= 8 × 4096 = 32,768개 연결 가능
Apache 최대 동시 처리 수:
= ServerLimit × ThreadsPerChild
= 16 × 25 = 400개 요청 가능
Tomcat 최대 동시 처리 수:
= maxThreads (기본: 200)
Nginx/Apache가 Tomcat을 프록시하는 경우, Tomcat의 maxThreads가 병목이 되지 않도록 상위 서버의 worker 수와 균형을 맞춰야 합니다.