Php – Multiple php-cgi.exe processes on IIS

iisiis-6PHP

The production server runs a PHP application on IIS 6.0. During the peak hours we have had a few issues where the php-cgi.exe processes increase in numbers and approach around 200. The server comes to a crawl and we have to restart the server a multiple times to restore the normal behavior. When the server is running normally, I have noticed that there are only 10-15 php-cgi.exe processes in the task manager.

What could be causing the php-cgi.exe processes to increase in number from 10-15 to around 200 during the peak hours? Where should I look for a cause?

Best Answer

IIS6 CGI is typically 1 request -> 1 process. 15 concurrent PHP-CGI processes is likely due to 15 concurrent PHP-CGI requests. Or you've got a high hang-rate for the PHP processes, and they're just not exiting properly.

On Windows, process startup isn't as cheap as on *nix (I'm told); Windows threads are lightweight and can be simply spun up within processes, but starting a process is expensive.

Starting a new process for each incoming request can range from "expensive" to "disastrous". It could simply be that your load is increased when you see 200 concurrent processes - i.e. you have 200 outstanding requests "in flight". At some point, performance will drop to where new work is coming in faster than the old work can possibly be completed, and if you're restarting the server to cope with that, you're just punishing the users. Who may well make another request straight away to retry it.

If your processes are loitering, your app might have a hanging bug too. But that's by the by.

Anyhoo, this is all a long-winded way of getting to: Have you tried FastCGI? http://learn.iis.net/page.aspx/247/using-fastcgi-to-host-php-applications-on-iis-60/

FastCGI on IIS allows reuse of an existing pool of non-exiting processes, so instead of one request starting, processing, and exiting a new process, each request is distributed to a pool of worker processes running (in this case) PHP-CGI.

Each PHP-CGI instance is kept alive while 1000+ requests are pumped through it, and then it's allowed to quit, and a new one is started in its place. From memory, there's a group of processes that do this concurrently to handle simultaneous requests (could be 4, 5 or 10 by default, configurable), and the performance should be (much) better.