본문 바로가기

Programming

Nginx, PHP-FPM에서 child process 개수 결정하기


현재 Nginx, PHP-FPM, PHP를 이용한 웹 서비스를 운영중인데, 서비스 사용자가 점점 늘어나면서 PHP-FPM에서 child process가 부족해서 lock 걸리고 있다는 에러를 뱉어냈었다. 그래서 child process의 개수를 적절한 개수로 늘리려고 정보를 찾다 괜찮은 글을 발견해서 번역 겸 기록으로 글을 쓰게 됐다. 

해당 링크는 https://www.kinamo.be/en/support/faq/determining-the-correct-number-of-child-processes-for-php-fpm-on-nginx

Introduction

Nginx + php-fpm을 이용해 웹 서비스를 운용하다 보면 아래와 같은 error 메시지를 볼 수 있는데, 이럴 때 어떻게 child processor의 개수를 결정하면 되는지에 대한 글이다.

[26-Mar-2015 10:10:04] WARNING: [pool www] server reached pm.max_children setting (35), consider raising it
[26-Mar-2015 12:04:52] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)

Determining the correct number of processes for PHP-FPM

기본적으로 서버의 실시간 log data를 이용하면 적절한 php-fpm 설정을 할 수 있다. 여기서 정확한 설정은 보통 cloud server 혹은 virtual server의 가용 Memory를 바탕으로 설정하게된다. 물론 PHP-FPM Processor 외에도 서버에서 돌아가는 다른 Processor도 고려해야한다.(MySQL 등등)

기본적인 PHP-FPM 설정을 살펴본다.
보통은 /etc/php5/fpm/ool.d/www.conf 경로에 config 파일이 있다.(Debian 기준)

나 같은 경우엔 Centos 6.7v 였는데 /etc/php-fpm.d/www.conf였다.

기본적으로는 아래와 같은 설정으로 되어있다.

pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 4
pm.max_spare_servers = 8

내가 운영하는 서버에선 아래와 같았다.

pm.max_children = 35
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 35

이 설정에서, 서버 성능에 적절한 값들을 찾기 위해서는 각각의 Processor(php-fpm, mysql etc.)들이 memory를 얼마나 먹고 있는지 계산해야한다.

아래 명령어를 입력하고 결과를 확인해보자.

ps -ylC php5-fpm --sort:rss

이렇게 했을 때 결과가 안나온다면 php5-fpmphp-fpm으로 변경하면 나온다.

아래 결과의 RSS를 보면 평균 사용 메모리를 KB로 표시해준다.

S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
S     0 24439     1  0  80   0  6364 57236 -      ?        00:00:00 php5-fpm
S    33 24701 24439  2  80   0 61588 63335 -      ?        00:04:07 php5-fpm
S    33 25319 24439  2  80   0 61620 63314 -      ?        00:02:35 php5-fpm

나 같은 경우엔 아래 결과와 같이 나왔다.

[root@ip-172-30-0-214 php-fpm]# ps -ylC php-fpm --sort:rss
S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
S     0 18756     1  0  80   0  6572 126494 ep_pol ?       00:00:00 php-fpm
S    48 18778 18756  0  80   0 16736 129301 skb_re ?       00:00:11 php-fpm
S    48 18792 18756  0  80   0 17680 129579 skb_re ?       00:00:11 php-fpm
S    48 20804 18756  0  80   0 17896 129807 skb_re ?       00:00:00 php-fpm
S    48 20800 18756  0  80   0 18044 128829 skb_re ?       00:00:00 php-fpm
S    48 20789 18756  0  80   0 18260 129868 skb_re ?       00:00:00 php-fpm
S    48 20802 18756  0  80   0 18500 129957 skb_re ?       00:00:00 php-fpm
...
...
40개 이상

내껄 기준으로 설명하면, 각 processor 당 19,000 KB를 사용하고, 이는 19MB이다.

위 명령어 외에 좀 더 확실해게 보려면 아래 명령어를 입력해보면 된다.

ps --no-headers -o "rss,cmd" -C php5-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'

위의 정보를 이용해서, PHP-FPM으로 사용가능한 memory / Processor 당 메모리 사용량으로 나누면 pm.max_children 개수를 정할 수 있다.

Calculating pm.max_children

예를 들어서, Server가 총 4GB의 RAM 용량을 갖고 있고, Server에 MySQL이 돌아가고 적어도 1GB RAM을 사용하고 있다면, 해서 PHP-FPM으로 사용할 수 있는 메모리는 2.5GB RAM이 된다.

평균 19MB를 사용하는 Processor를 기준으로 하면 pm.max_children2560MB / 19MB = 134로 계산해서 총 134개의 child process를 띄울 수 있다.

그러면 대충 설정을 아래와 같이 하면 될 것 같다.

pm.max_children = 130
pm.start_servers = 30
pm.min_spare_servers = 30
pm.max_sapre_servers = 100
pm.max_requests = 500