Configuring PHP-FPM For High Network Traffic

jake

Jake Casto

Posted on January 23, 2018

Configuring PHP-FPM For High Network Traffic

php-fpm logo

Maintaining a constant response time on a server with high network traffic while using PHP is probably the hardest & most annoying thing I've done in my career. Switching from Apache to Nginx was a huge performance upgrade... that lasted for a solid half hour before the RPS (requests-per-second) was causing the stack to overflow once again.

I started browsing Stack Overflow & Google (devs best & worst friend/enemy) for answers, I found a few posts that showed how to fix the issue (PHP-FPM conf) but didn't explain anything. As a hands-on developer, I wanted to know how things worked.

Originally my PHP-FPM conf looked something like this



[www]

user = apache
group = apache

listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1

pm = dynamic

pm.max_children = 200

pm.start_servers = 20

pm.min_spare_servers = 10
pm.max_spare_servers = 20

pm.max_requests = 1000


Enter fullscreen mode Exit fullscreen mode

I started reading into what pm = dynamic meant and I found this (in another conf file haha)

dynamic - the number of child processes are set dynamically based on the following directives. With this process management, there will be always at least 1 children.

Hold on... are all 200 children being spawned on startup? Are they always idle?

Yes & Yes (i think). I started viewing and recording memory usage of the apache pool using ps aux |grep apache. No matter how many requests were being processed (0 requests - 1000 requests) there were always 200 children alive. Don't get me wrong, I love kids but 200 at once for no reason is a bit much.

After spending a few hours screwing with my PHP-FPM conf and running stress tests I came up with this



[www]

user = apache
group = apache

listen = 127.0.0.1:9001

listen.allowed_clients = 127.0.0.1

pm = ondemand
pm.max_children = 200
pm.process_idle_timeout = 1s
pm.max_requests = 1000


Enter fullscreen mode Exit fullscreen mode

I ran another stress test: 2000 RPS (requests-per-second) for one min and the average response time went from 1000MS to 120MS.

What happened?

PHP-FPM's PM (Pool Manager) was spawning 200 children on startup, even though those children were idle the PM was using unnecessary resources to manage the children. The switch from dynamic to ondemand allowed children to be spawned when needed and killed them after 1s of inactivity.

Feel free to critique this post, I have little knowledge of how PHP-FPM's pool manager works. I felt that it might be helpful to someone in a bind with PHP-FPM.

EDIT: Some info in this article is incorrect e.g I confused dynamic with static spawning 200 children on startup. However, I still use this same setup on new servers and it performs so much better than any other config I've used.

💖 💪 🙅 🚩
jake
Jake Casto

Posted on January 23, 2018

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related