높은 트래픽을 가진 웹사이트는 서비스의 특별한 구성이 필요합니다. 선택한 서비스에 따라 VPS 서버의 높은 성능을 달성하기 위한 권장 사항이 있습니다.
단순히 리소스를 늘리는 것만으로는 VPS 서버의 높은 성능을 얻을 수 없습니다. 서비스 구성도 필요합니다.
기본적으로 서비스는 낮거나 중간 정도의 트래픽을 가진 일반적인 프로젝트에 적합한 기본 설정을 가지고 있습니다.
명확성을 위해 트래픽 기준을 정의하겠습니다:
- 낮은 웹사이트 트래픽: 월 10,000회 방문 이하(하루 약 300회, 5분마다 1회 방문).
- 중간 웹사이트 트래픽: 월 10,000~90,000회 방문—평균 50,000회/월(하루 약 1,600회, 분당 1회 방문).
- 높은 웹사이트 트래픽: 월 100,000회 방문 이상, 즉 분당 2회 방문 이상.
nginx를 프록시 웹 서버로 사용하고 php-fpm(이 경우 php8.3-fpm)을 주요 처리기로 사용하는 구성을 분석해 보겠습니다.
우리는 Linux Debian 12를 실행하는 VPS 서버를 사용했으며, 6개의 CPU 코어, 8GB RAM, 50GB SSD를 갖추고 있습니다.
우리는 php8.3-fpm에 대해 특별히 성능을 최적화할 것입니다. 기본 구성으로 링크 분석 스크립트를 실행했으며, 몇 분 후 요청 속도가 초당 9개에서 5개로 떨어졌습니다. 5분 더 지나자 성능은 초당 1.5개 요청으로 감소했고, 서비스가 병목 현상을 일으키기 시작하여 곧 Bad Gateway 오류를 반환했습니다.
그동안 서버 부하가 크게 증가하지 않았으며, 요청을 처리할 수 있는 충분한 리소스가 여전히 남아 있었습니다.
1. 새로운 php-fpm 구성 파일
/etc/php/8.3/fpm/pool.d/domain.conf 에 새 구성 파일을 만듭니다.
기존 파일은 www.conf.bak 으로 이름을 변경합니다. 이렇게 하면 사용되지 않으며, 필요할 경우 .bak 접미사를 제거하여 복원할 수 있습니다.
2. 구성 세부 사항
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; Process manager
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500
pm.max_spawn_rate = 32
pm.process_idle_timeout = 10s
; Connection settings
listen.backlog = 65535
listen.allowed_clients = 127.0.0.1
; Timeouts
request_terminate_timeout = 30s
request_slowlog_timeout = 5s
slowlog = /var/log/php8.3-fpm/slow.log
; Status monitoring
pm.status_path = /fpm-status
ping.path = /ping
ping.response = pong
; Logging
access.log = /var/log/php8.3-fpm/access.log
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{milli}dms"
catch_workers_output = yes
decorate_workers_output = no
; Security
security.limit_extensions = .php .php3 .php4 .php5 .php7 .php8
clear_env = no
; Performance tweaks
rlimit_files = 65535
rlimit_core = unlimited
; PHP settings
php_admin_value[error_log] = /var/log/php8.3-fpm/error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 128M
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 32M
php_admin_value[max_execution_time] = 30
php_admin_value[session.gc_maxlifetime] = 1440
3. 추가 설정
로그 디렉토리가 존재하지 않으면 생성합니다:
mkdir -p /var/log/php8.3-fpm
3.1 구성 주석
- listen = 127.0.0.1:9000 - nginx 구성과 일치해야 하며, 그 반대도 마찬가지입니다.
- pm.max_children = 50 - 사용 가능한 RAM에 따라 달라집니다(자식 프로세스당 50MB → PHP에 약 2GB).
- pm.start_servers = 10 - pm.max_children`의 약 20%.
- pm.max_requests = 500 - 메모리 누수를 방지하기 위해 500개 요청 후 워커를 재시작합니다(방문자에게는 감지되지 않으며 작동에 영향을 미치지 않음).
- request_terminate_timeout = 30s - 멈춘 요청을 종료합니다.
- request_slowlog_timeout = 5s - 느린 요청을 기록합니다.
- slowlog = /var/log/php8.3-fpm/slow.log
CMS 기반 사이트의 경우 느린 요청 로그는 호출 스택을 표시하므로 큰 도움이 되지 않을 수 있지만, 요청 시작과 종료의 시간 간격에 대한 유용한 정보를 제공할 수 있습니다.
/fpm-status 를 모니터링하려면 nginx 서버 블록에 다음을 추가합니다:
location = /fpm-status {
allow 127.0.0.1; # 로컬 액세스만 허용
allow 192.168.10.100; # 또는 신뢰할 수 있는 네트워크
deny all; # 나머지 모두 차단
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
출력 내용은 다음과 같습니다:
pool: www
process manager: dynamic
start time: 04/Jun/2025:18:16:50 +0000
start since: 814
accepted conn: 239
listen queue: 0
max listen queue: 0
listen queue len: 128
idle processes: 9
active processes: 1
total processes: 10
max active processes: 3
max children reached: 0
slow requests: 0
4. 새 구성 적용
구성 파일에 오류가 있는지 확인합니다:
php-fpm8.3 -t
오류가 없으면 서비스를 재시작합니다:
systemctl restart php8.3-fpm
5. 재테스트
새 구성으로 비슷한 테스트를 진행했을 때 CPU 부하가 눈에 띄게 증가했지만, 성능은 몇 분 후 20%만 감소(초당 9개 요청에서 7개로)하고 안정화되었습니다. 모든 요청(25분 동안 약 10,000개 요청, 즉 분당 400개 요청 또는 초당 약 7개 요청)은 상태 코드 200으로 성공적으로 처리되었습니다.
동시에 테스트하며 웹사이트 페이지를 탐색했을 때 시각적으로 성능이 눈에 띄게 빨라졌습니다. 이제 이 웹 서비스 구성으로 서버 리소스가 이전처럼 유휴 상태로 남아 있지 않고 완전히 활용됩니다.