제가 2018년 1월부터 2021년 9월까지, 총 3년 9개월을 다녔던 회사에서 근무하면서 직접 경험한 내용을 바탕으로 공부하고 알게된 지식을 간단하게 정리하는 글입니다.
TCP 통신과 Linux Socket 관련 내용은 여기에서 확인해주세요.
웹서버와 외부 프로토콜을 연결시켜주는 표준 프로토콜로서, 기본적으로 Request 요청별로 프로세스를 생성하여 처리하는 방식을 의미합니다.
Request가 발생할 때 마다 프로세스를 생성하여 처리하고, 프로세스를 종료하는 CGI의 단점을 개선한 방식으로, Request 요청을 처리할 프로세스를 미리 만들어두고 재사용하는 방식으로 처리를 합니다.
php-fpm은 PHP FastCGI Process Manager의 약자로서, PHP 스크립트를 실행하는 FastCGI 서버로 동작합니다.
php-fpm은 Worker 프로세스를 관리하는 Master 프로세스와 PHP 스크립트를 실행하는 Worker 프로세스로 구분되며, Master 프로세스는 웹 서버(예: Nginx, Apache 등)로부터 FastCGI 요청을 수신받아 Worker 프로세스로 전달하는 역할도 합니다.
참고!
php-fpm은max_children
옵션을 통해 미리 만들어둘 프로세스의 수량을 지정할 수 있습니다.
메모리 누수 등의 문제를 최소화하기 위해max_requests
옵션도 제공합니다.그 외 FastCGI 동작에 관련된 많은 설정을 제공하고 있습니다.
php-fpm은 일반적으로 Server의 역할을 수행하기 때문에 LocalPort를 고갈시키지 않습니다.
하지만 소스 코드 내에 MySQL, Redis 등 외부 서비스로 연결하는 로직이 포함되면 이야기가 달라집니다.
PHP는 MySQL, Redis 등 외부 서비스로 연결하는 과정에서 TCP 소켓을 생성하게 되는데, 이 과정에서 PHP는 커널에게 LocalPort을 요청하게 되고, 이후 외부 서비스와의 연결을 Disconnect하는 과정에서 소켓의 상태를 TIME_WAIT
로 변경합니다.
참고!
TIME_WAIT
상태를 갖는 소켓은 패킷 유실 등의 처리를 위해 약 1분동안 대기한 다음 연결을 종료하게 됩니다.
여기서 중요한 점은 php-fpm은 Request 단위로 처리를 한다는 점입니다.
만약 1분도 안되는 시간에 트래픽(사용자의 요청)이 급격하게 증가하면 TIME_WAIT
상태를 갖는 소켓으로 인해 리눅스의 LocalPort가 고갈되어 서비스에 장애가 발생할 수 있습니다.
참고!
소켓은 TCP 통신을 위해 생성된 File Descriptor를 의미합니다. 따라서 Process별로 가질 수 있는 File Descriptor 설정에도 영향을 받습니다.