티스토리 뷰

PHP FPM child process 최대 개수 계산하기

얼마전에 PHP-FPM 의 Process Manger의 설정값을 잘 못 건들였다가 Load Balancing 설정되어 있는 서버 4대가 순차적으로 Memory out 으로 인해 Hang-Up 되는 사태가 발생하였다. (OTL…)

원인을 살펴보니 (Core dump를 확인할 능력이 안되서) log 들을 살펴보니, PHP-FPM error log 에서 문제점을 발생했음을 확인할 수 있었다.

[pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 15 idle, and 51 total children
[pool www] server reached pm.max_children setting (140), consider raising it
[pool www] child 4012 exited with code 0 after 20966.666371 seconds from start
[pool www] child 17712 started

최대 스페어 서버나 시작 서버들을 올려줄 필요가 있다 라고 하는데… 이것 때문에 서버가 행업이 걸렸을거 같진 않고, /var/log/message 를 살펴보니 다음과 같은 로그가 남겨져 있었다.

Jan  2 14:00:55 cobuy-0688 kernel: [<ffffffff81131ce0>] ? out_of_memory+0x220/0x3c0
Jan  2 14:00:55 cobuy-0688 kernel: Out of memory: Kill process 42643 (php-fpm) score 5 or sacrifice child

이 메시지가 1849개가 남겨져 있었다.

왜 메모리가 넘치도록 사용했는지 php-fpm의 설정을 확인해보았습니다.

pm.max_children = 65535
pm.start_servers = 64
pm.min_spare_servers = 12
pm.max_spare_servers = 65535
pm.max_requests = 1024

… 최대 프로세스 개수가 65535로 설정이 되어 있었던 겁니다. 프로세스 한개당 10M로 잡아도.. 655350MB.. 650G의 메모리를 사용하겠다라는 저 설정값. localhost 통신에서 sock 통신으로 바꾼지 꽤 됐는데 문제가 늦게 발생했던게 운이 좋았다라고 해야하나요.. 어쨋든 php-fpm 데몬이 위치한 서버의 스펙에 맞게 개수를 조절하는 방법에 대해 알아보겠습니다.

서버 메모리 확인

우선 php-fpm 이 운영되는 서버의 메모리 용량부터 확인해봐야합니다.

[]$ free -m
             total       used       free     shared    buffers     cached
Mem:         32057      11608      20449          0        262       3027
-/+ buffers/cache:       8318      23738
Swap:         2047          0       2047

총 메모리는 32GB 네요.

저는 보통 메모리의 10% 정도는 예기치 못한 돌발 상황에 대응하기 위해, 나머지 20%는 시스템에서 사용할 수 있도록 총 30% 메모리를 남겨두고 70%의 메모리를 전체 가용합니다. 디비 서버는 따로 있거든요.

32GB * 0.7 = 22.4GB

22.4GB 를 최대한 쓰도록 해야겠습니다.

PHP-FPM Child Process 메모리 확인

PHP-FPM의 Child Process 하나당 메모리를 얼마나 점유하고 있는지 확인해보겠습니다.

[]$ ps -ylC php-fpm --sort:rss
S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
S     0 14180     1  0  80   0  6456 118927 ep_pol ?       00:00:00 php-fpm
S   505 14200 14180  2  80   0 65372 125903 skb_re ?       00:04:27 php-fpm
S   505 24758 14180  2  80   0 66468 126242 skb_re ?       00:02:41 php-fpm
S   505 14194 14180  2  80   0 69224 125142 skb_re ?       00:04:30 php-fpm
S   505 14227 14180  0  80   0 71212 124665 skb_re ?       00:00:09 php-fpm
S   505 14233 14180  0  80   0 71600 125312 skb_re ?       00:00:09 php-fpm
S   505 23741 14180  2  80   0 72136 127625 skb_re ?       00:02:47 php-fpm
S   505 14209 14180  2  80   0 73928 128341 skb_re ?       00:04:30 php-fpm
S   505 14229 14180  0  80   0 75344 125433 skb_re ?       00:00:09 php-fpm
S   505 14228 14180  0  80   0 75724 126018 skb_re ?       00:00:09 php-fpm
S   505 14222 14180  0  80   0 75800 125371 skb_re ?       00:00:10 php-fpm
S   505 14215 14180  2  80   0 76312 128568 skb_re ?       00:04:28 php-fpm
S   505 14225 14180  0  80   0 77528 126725 skb_re ?       00:00:09 php-fpm
S   505 14230 14180  0  80   0 78124 126786 skb_re ?       00:00:08 php-fpm
S   505 15547 14180  0  80   0 78436 125359 skb_re ?       00:00:07 php-fpm
S   505 33589 14180  1  80   0 80516 130325 skb_re ?       00:01:33 php-fpm
S   505 14236 14180  0  80   0 81704 125295 skb_re ?       00:00:10 php-fpm
S   505 24760 14180  1  80   0 81712 130232 skb_re ?       00:02:36 php-fpm
S   505 14211 14180  2  80   0 83064 131278 skb_re ?       00:04:31 php-fpm
S   505 14231 14180  0  80   0 83076 127049 skb_re ?       00:00:09 php-fpm
S   505 23744 14180  2  80   0 83912 130877 skb_re ?       00:02:51 php-fpm
S   505 14207 14180  2  80   0 84172 130352 skb_re ?       00:04:24 php-fpm
S   505 23739 14180  2  80   0 84408 130936 skb_re ?       00:02:46 php-fpm
S   505 14226 14180  0  80   0 84568 128005 skb_re ?       00:00:09 php-fpm
S   505 14213 14180  2  80   0 85184 130977 skb_re ?       00:04:23 php-fpm
S   505 14212 14180  2  80   0 85620 131857 skb_re ?       00:04:25 php-fpm
S   505 14725 14180  0  80   0 85732 126959 skb_re ?       00:00:10 php-fpm
S   505 38954 14180  0  80   0 86456 123358 skb_re ?       00:00:06 php-fpm
S   505 24759 14180  1  80   0 88348 130162 skb_re ?       00:02:37 php-fpm
S   505 14235 14180  0  80   0 88968 129295 skb_re ?       00:00:09 php-fpm
S   505 14206 14180  2  80   0 89136 130064 skb_re ?       00:04:21 php-fpm
S   505 14234 14180  0  80   0 89668 128506 skb_re ?       00:00:09 php-fpm
S   505 14232 14180  0  80   0 89936 129404 skb_re ?       00:00:08 php-fpm
S   505 38959 14180  0  80   0 90164 123678 skb_re ?       00:00:07 php-fpm
S   505 14252 14180  0  80   0 91452 128697 skb_re ?       00:00:09 php-fpm
S   505 14223 14180  0  80   0 92044 129660 skb_re ?       00:00:10 php-fpm
S   505 14224 14180  0  80   0 92412 128066 skb_re ?       00:00:10 php-fpm
S   505 23740 14180  2  80   0 92452 132907 skb_re ?       00:02:49 php-fpm
S   505 14221 14180  0  80   0 93412 126675 skb_re ?       00:00:10 php-fpm
S   505 23745 14180  2  80   0 94288 133271 skb_re ?       00:02:51 php-fpm
S   505 15570 14180  2  80   0 94652 132943 skb_re ?       00:04:24 php-fpm
S   505 14196 14180  2  80   0 95224 133018 skb_re ?       00:04:23 php-fpm
S   505 14216 14180  2  80   0 96244 133532 skb_re ?       00:04:24 php-fpm
S   505 14201 14180  2  80   0 98708 134614 skb_re ?       00:04:28 php-fpm
S   505 33580 14180  1  80   0 99364 134138 skb_re ?       00:01:36 php-fpm
S   505 33606 14180  1  80   0 99388 134493 skb_re ?       00:01:36 php-fpm
S   505 33608 14180  1  80   0 99544 134124 skb_re ?       00:01:33 php-fpm
S   505 33600 14180  1  80   0 100012 135863 skb_re ?      00:01:35 php-fpm
S   505 24757 14180  1  80   0 100520 135071 skb_re ?      00:02:37 php-fpm
S   505 19616 14180  2  80   0 100616 135121 skb_re ?      00:03:29 php-fpm
S   505 24754 14180  2  80   0 100736 134731 skb_re ?      00:02:41 php-fpm
S   505 14220 14180  2  80   0 100796 134681 skb_re ?      00:04:22 php-fpm
S   505 14198 14180  2  80   0 100828 134741 skb_re ?      00:04:23 php-fpm
S   505 33605 14180  1  80   0 100944 136107 skb_re ?      00:01:39 php-fpm
S   505 20315 14180  2  80   0 101140 135118 skb_re ?      00:03:21 php-fpm
S   505 14673 14180  2  80   0 101212 135089 skb_re ?      00:04:25 php-fpm
S   505 14197 14180  2  80   0 101364 135864 skb_re ?      00:04:22 php-fpm
S   505 14205 14180  2  80   0 101692 135125 skb_re ?      00:04:19 php-fpm
S   505 14651 14180  2  80   0 101764 134761 skb_re ?      00:04:25 php-fpm
S   505 14204 14180  2  80   0 101832 135213 skb_re ?      00:04:18 php-fpm
S   505 14214 14180  2  80   0 101876 134818 skb_re ?      00:04:22 php-fpm
S   505 14202 14180  2  80   0 101896 132954 skb_re ?      00:04:23 php-fpm
S   505 33615 14180  1  80   0 102112 136177 skb_re ?      00:01:34 php-fpm
S   505 14254 14180  2  80   0 102156 135068 skb_re ?      00:04:23 php-fpm
S   505 23742 14180  2  80   0 102204 135062 skb_re ?      00:02:49 php-fpm
S   505 14193 14180  2  80   0 102340 135009 skb_re ?      00:04:25 php-fpm
S   505 14219 14180  2  80   0 102668 135118 skb_re ?      00:04:29 php-fpm
S   505 14191 14180  2  80   0 103420 135479 skb_re ?      00:04:25 php-fpm
S   505 14253 14180  2  80   0 103568 135039 skb_re ?      00:04:18 php-fpm
S   505 14208 14180  2  80   0 103664 135249 skb_re ?      00:04:23 php-fpm
S   505 14251 14180  2  80   0 105732 134689 skb_re ?      00:04:24 php-fpm
S   505 14210 14180  2  80   0 107360 135121 skb_re ?      00:04:22 php-fpm
S   505 14199 14180  2  80   0 107664 135220 skb_re ?      00:04:23 php-fpm
R   505 14217 14180  2  80   0 108992 137301 -    ?        00:04:20 php-fpm
S   505 14189 14180  2  80   0 109276 135243 skb_re ?      00:04:22 php-fpm
S   505 14195 14180  2  80   0 109280 135174 skb_re ?      00:04:27 php-fpm
S   505 23736 14180  2  80   0 109656 137430 sk_wai ?      00:02:45 php-fpm
S   505 14192 14180  2  80   0 114484 137310 skb_re ?      00:04:22 php-fpm
S   505 38958 14180  0  80   0 115004 124062 skb_re ?      00:00:06 php-fpm
R   505 24756 14180  2  80   0 115688 138494 -    ?        00:02:43 php-fpm
S   505 14203 14180  2  80   0 116192 137493 skb_re ?      00:04:22 php-fpm
S   505 14218 14180  2  80   0 116600 137542 skb_re ?      00:04:27 php-fpm
S   505 14190 14180  2  80   0 118844 138210 skb_re ?      00:04:28 php-fpm
S   505 14183 14180  0  80   0 119244 123488 skb_re ?      00:00:18 php-fpm
S   505 38957 14180  0  80   0 124044 124523 skb_re ?      00:00:06 php-fpm
S   505 14182 14180  0  80   0 129664 124143 skb_re ?      00:00:18 php-fpm
S   505 14181 14180  0  80   0 138164 124214 skb_re ?      00:00:18 php-fpm
S   505 14188 14180  0  80   0 148948 124145 skb_re ?      00:00:17 php-fpm
S   505 14187 14180  0  80   0 149988 125663 skb_re ?      00:00:18 php-fpm
S   505 14646 14180  0  80   0 153444 123429 skb_re ?      00:00:19 php-fpm
S   505 14186 14180  0  80   0 155476 126902 skb_re ?      00:00:16 php-fpm
S   505 16458 14180  0  80   0 160924 136567 skb_re ?      00:00:18 php-fpm
S   505 14185 14180  0  80   0 162488 132069 skb_re ?      00:00:17 php-fpm
S   505 14184 14180  0  80   0 165656 123379 skb_re ?      00:00:21 php-fpm

RSS 는 Process 가 물리적 메모리를 점유하고 있는 용량을 KB로 나타냅니다.
저의 경우에는 99MB 가 평균값으로 보이는 군요.

보다 정확한 값을 위해서 다음과 같은 명령으로 확인 할 수 있습니다.

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

96M가 평균값이네요. 그러면 위에서 풀 가용하려고 했던 값과 평균값을 나누면 됩니다.

22,937.6MB / 96M = 238.933333333333333333333333333333

소수점 자리는 버려서 238 개의 php-fpm child process 를 사용할 수 있겠네요.

pm.max_children = 238
pm.start_servers = 64
pm.min_spare_servers = 32
pm.max_spare_servers = 128
pm.max_requests = 512

pm.max_children 를 설정하면 238개까지 동시에 자식 프로세스가 동작할 수 있습니다. 이 이상은 생성되지 않죠.

pm.start_servers 는 php-fpm 을 실행할 때 생성하려는 자식 프로세스의 개수입니다.

pm.min_spare_serversidle 상태의 자식 프로세스 개수가 이 개수보다 작으면 몇몇 자식 프로세스를 생성합니다.

pm.max_spare_serversidle 상태의 자식 프로세스 개수가 이 개수보다 크면 몇몇 자식들을 죽입니다.(무섭네요)

pm.max_requests 는 respawning 하기 전에 각 자식 프로세스가 처리해야할 요청 개수입니다. 이 값이 높으면, 리스폰 하기 위해서는 엄청나게 일을 해야합니다.