I have a PHP application which uses AJAX to get information - in the back, it uses a PHP MySQLi singleton. The AJAX-requests are send every 0.5 second and they read some stuff out of the database and deliver it as a JSON String back to website.
When I open the website several times (in different tabs), I then get an error because PHP, or rather apache, could not "fork another process". My server has enough RAM, but the problem is taht the process-limit of 130 processes was reached.
cat /proc/user_beancounters
---------------------------
| held | maxheld |
numproc | 130 | 130 |
So, I would like to know if it's possible that the singleton is fault (like "why singletons are bad") or could you imagine another error source? The error source, that so many MySQL-processes get started and reach the max. limit?
I would recommend you to post the code of your singleton and ajax back-end. It's hard to make a statement saying that your singleton or ajax back-end is at fault if we are not able to look at it.
I would probably look at the number of connections as a more likely cause though. If this is not a local application it's not uncommon that the actual requests take more than 0.5s. So one request might not be done before you call another. This could over time build up a queue that the SQLi backend is not able to process fast enough and the process count would start to rise since new requests were added to the queue every 0.5s for each connected client.
How does the ajax back-end look? Does it run a query straight away? Does it launch another php instance? How many concurrent connection is the webserver and database configured for?
All these things will heavily determine how your application behaves. Also, as stated. Note that even if you use a singleton it does NOT live past the execution of your ajax call. Each time you make a call your php application starts from scratch and your singleton is created from scratch once again.
You could set up an application (written in PHP or other) that would actually run all the time and make use of a main loop. Then you could either make that listen to a specific socket or by other means have your ajax back-end pass data to that application. The running application could then handle the database back-end and return the data to the ajax back-end that would return the reply. This way the database handler would not recreate your singleton all the time. But you would very likely still run into queue issues if there are a lot of clients making requests that require a database look-up every 0.5s.
Good luck!
This has nothing to do with your singleton its that youre making a request to the server every .5 seconds the pages making the requests are available to a user base then you have to also multiply that by the number of users that have the page(s) open which make the requests. IF you really need to pull the server at this rate you might wan to look into some other technology like Comet.
Of course if the requests take a long time to process you could optimize those and maybe reduce the number of forks needed to handle the requests but this is still going to be an ongoing problem.
The first thought that comes to mind (as mentioned by the others) is the frequency by which you ping the server. Why do you need that to be so high? That just creates more processes (overlapping like others have suggested) and wastes processing cycles.
A better approach is something called long polling. This is a process by which the client browser sends a request, but doesn't expect a response back immediately. Instead the server hangs on to that request until it has something to send back to the client. This is far more efficient and is actually what the APE project uses (Ajax Push Engine - http://www.ape-project.org/).
Check out what they are doing. I would be willing to bet that it will be right for what your trying to accomplish. And it will reduce your resource consumption.
I am not sure I got that right...
When the AJAX-Request is processed a new PHP process is run; the singleton is only available within this process, singletons are not shared between several PHP processes. So each Request ends up with its own database connection, the singleton just makes sure that there is not more than one connection per process.
You might want to take a look at persistent connections, though I prefer not to use them; and I am not sure if they are available with MySQLi at all.