Ubuntu 환경에서 PHP-FPM이 “가끔씩” 멈추거나(응답 지연/타임아웃), 재시작하면 잠깐 정상인데 다시 문제를 반복하는 경우가 있습니다. 특히 Redis를 세션/캐시로 쓰는 서비스라면, PHP-FPM 자체 문제처럼 보여도 실제로는 Redis 연결 지연, 소켓 권한, 프로세스 풀 설정, 느린 스크립트가 엮여서 발생하는 경우가 많습니다.

서버를 감싸는 안전장치와 복구 흐름 일러스트

아래는 장애 시 안전하게 되돌릴 수 있는 롤백/복구 경로까지 포함한, “증상 → 점검 순서(체크리스트) → 해결 단계” 흐름의 실전 절차입니다.

1) 증상 패턴 정리: “멈춤”이 실제로는 어디서 생기는지

먼저 현상을 2~3줄로 고정해두면, 점검이 빨라집니다. 대표 패턴은 아래 중 하나로 수렴합니다.

  • 502/504 증가: Nginx(또는 Apache)에서 upstream timeout, gateway timeout이 늘어남
  • 간헐적 무한 로딩: 특정 요청만 오래 걸리고 결국 timeout
  • PHP-FPM 재시작 후 잠깐 정상: worker가 누수/대기열 적체로 서서히 악화
  • Redis 사용 시 더 자주 발생: 세션/캐시 접근이 많은 트래픽에서 특히 두드러짐

이 글의 핵심은 “바로 고치는” 것뿐 아니라, 되돌릴 수 있게 변경 범위를 작게 유지하는 것입니다(설정 백업/롤백, 임시 완화, 원인 해결 순서).

2) 점검 순서 체크리스트(로그·상태·연결)

장애 중이거나 직후에 아래 순서로 확인하면 원인 좁히기가 쉽습니다.

  • 웹서버 에러: Nginx error.log에서 upstream timeout/connection reset 여부
  • PHP-FPM 상태: systemd 상태, 최근 재시작/크래시 흔적
  • PHP-FPM 로그: slowlog, error log에 “child exited”, “pool reached max_children” 같은 메시지
  • 소켓/포트: php-fpm이 listen하는 unix socket 파일 존재/권한/소유자
  • 리소스: CPU, 메모리, swap, load average 급등 여부
  • Redis 연결: redis-server 지연/재시작, maxclients, timeouts, 연결 에러
  • 애플리케이션: 특정 endpoint만 느린지(외부 API/DB/Redis) 확인

로그와 상태를 확인하는 점검 체크리스트 이미지

가능하면 “장애 직후 5분 안에” 로그를 잡아두는 게 중요합니다. 간헐 장애는 시간이 지나면 증거가 사라지기 쉬워요.

3) 즉시 복구(임시 완화): 서비스 살리기 + 안전장치

먼저 사용자가 체감하는 장애를 줄이는 임시 완화를 하고, 그 다음에 원인 분석으로 넘어갑니다. 단, 임시 조치는 되돌리는 방법을 같이 준비합니다.

  • PHP-FPM graceful 재시작: 설정 변경 전이라도 hang가 의심되면 우선 재기동으로 큐를 비움
  • 웹서버 upstream timeout을 과하게 늘리지 않기: 근본 문제를 가릴 수 있으니 “소폭”만 조정
  • Redis가 원인 의심 시: 짧은 기간 캐시/세션 의존도를 낮추는 설정(가능한 범위에서)
  • 롤백용 백업: PHP-FPM pool 설정, PHP ini, 웹서버 upstream 설정 파일을 변경 전 복사

변경 전 백업은 “파일 하나 복사”면 충분합니다. 예: /etc/php/*/fpm/pool.d/www.conf, /etc/php/*/fpm/php.ini, /etc/nginx/sites-available/* 등을 타임스탬프 붙여 저장해두세요.

또한 장애가 반복된다면, 임시로 PHP-FPM 리스타트 정책을 확인해 “죽었을 때 자동으로 살아나게” 만드는 것도 복구 경로에 포함됩니다(원인 해결과 별개로 안전장치).

4) PHP-FPM에서 자주 터지는 지점: 풀 설정, max_children, slowlog

간헐적인 멈춤은 “worker가 다 찬 상태”에서 많이 발생합니다. 특히 다음 신호가 보이면 PHP-FPM 풀 튜닝이 필요합니다.

  • pool reached max_children 로그가 반복
  • 요청이 몰릴 때만 502/504
  • 특정 느린 요청이 worker를 오래 점유

우선 확인 포인트는 이렇습니다.

  • pm: dynamic/ondemand/static 중 무엇인지
  • pm.max_children: 메모리 여유 대비 너무 낮거나 너무 높지 않은지
  • request_terminate_timeout: 무한 대기 요청을 끊어주는 안전장치로 유효한지
  • slowlog: 실제로 어떤 PHP 함수/코드에서 멈추는지 증거 확보

PHP-FPM과 Redis 병목을 나타낸 흐름도

권장 접근은 “증거( slowlog ) 확보 → 작은 폭으로 조정 → 롤백 가능” 순서입니다. 예를 들어 max_children을 무작정 키우면, 트래픽 순간에 메모리를 다 써서 OOM으로 더 크게 터질 수 있습니다.

5) Redis 연동 점검: 연결 지연, timeouts, 세션/캐시 병목

Redis가 직접 다운이 아니어도, 연결이 지연되면 PHP-FPM worker가 Redis I/O에서 대기하면서 전체가 멈춘 것처럼 보일 수 있습니다.

  • redis-server 상태: 재시작/크래시 흔적, 메모리 사용량, eviction 여부
  • 연결 수: maxclients 근접, 연결 폭증(커넥션 누수 의심)
  • 네트워크: Redis가 원격이라면 지연/패킷 드롭이 없는지
  • PHP Redis 클라이언트 설정: connect timeout/read timeout이 비정상적으로 긴지

세션을 Redis에 저장하는 경우, Redis 장애는 로그인/장바구니/CSRF 등 “거의 모든 요청”을 막습니다. 이때의 안전장치는 두 가지입니다.

  • 짧은 timeout으로 “빨리 실패”하게 만들고(서비스는 degraded)
  • 가능하면 일시적으로 세션 저장소를 file로 롤백할 수 있는 절차를 준비

중요: 세션 저장소 롤백은 사용자 로그인이 풀리거나 세션이 초기화될 수 있어 영향도가 큽니다. 그래서 “즉시 적용”이 아니라, 장애가 커질 때 최후 수단으로 문서화해두는 게 좋습니다.

6) 롤백/복구 경로 설계: 변경 단위, 검증, 되돌리기

간헐 장애는 한 번에 여러 설정을 만지면 원인도, 롤백도 어려워집니다. 아래처럼 “변경 단위”를 작게 쪼개면 안전합니다.

  • 1단계(관측 강화): PHP-FPM slowlog 활성화, 로그 레벨 조정(성능 영향 최소로)
  • 2단계(안전장치): request_terminate_timeout, process manager 조정(소폭)
  • 3단계(병목 해소): 느린 코드/쿼리/Redis 호출 최적화 또는 캐시 키 설계 수정
  • 4단계(인프라): 메모리 증설, PHP-FPM 풀 분리, Redis 분리/HA는 마지막

각 단계마다 아래 3가지를 세트로 남기면, 다음 장애 때 복구가 빨라집니다.

  • 적용 전 백업 파일: 원본 설정 스냅샷(파일 복사로 충분)
  • 검증 방법: 특정 URL 호출, 에러 로그 감소, p95 응답시간 등 “확인 기준”
  • 되돌리기 명령/절차: 백업 파일 복원 후 서비스 재시작, 그리고 재발 여부 확인

팁: 설정 변경 후에는 “정상처럼 보이는지”만 보지 말고, 5~10분 뒤에도 max_children/timeout이 재발하지 않는지까지 확인하는 게 좋습니다(간헐 장애는 지연 재발이 흔합니다).

마무리

Ubuntu에서 PHP-FPM이 간헐적으로 멈출 때는, PHP-FPM 자체 문제뿐 아니라 Redis 지연/연결 이슈가 원인인 경우가 많습니다. 그래서 로그와 상태를 먼저 묶어서 보고, 임시 복구로 서비스를 살린 뒤, slowlog 같은 증거 기반으로 풀 설정과 Redis 연동을 단계적으로 손보는 흐름이 안전합니다.

가장 큰 차이는 “해결”보다 롤백/복구 경로를 함께 설계하는 것입니다. 변경을 작게, 검증을 명확히, 되돌리기를 쉬운 형태로 남겨두면 같은 문제가 다시 와도 대응 시간이 크게 줄어듭니다.