Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>When you use Apache with mod_php apache is enforced in <code>prefork</code> mode, and not <code>worker</code>. As, even if php5 is known to support multi-thread, it is also known that some php5 libraries are not behaving very well in multithreaded environments (so you would have a locale call on one thread altering locale on other php threads, for example).</p> <p>So, if php is not running in cgi way like with php-fpm you have mod_php inside apache and apache in prefork mode. On your tests you have simply commented the prefork settings and increased the worker settings, what you now have is default values for prefork settings and some altered values for the shared ones :</p> <pre><code>StartServers 20 MinSpareServers 5 MaxSpareServers 10 MaxClients 1024 MaxRequestsPerChild 0 </code></pre> <p>This means you ask apache to start with 20 process, but you tell it that, if there is more than 10 process doing nothing it should reduce this number of children, to stay between 5 and 10 process available. The increase/decrease speed of apache is 1 per minute. So soon you will fall back to the classical situation where you have a fairly low number of free available apache processes (average 2). The average is low because usually you have something like 5 available process, but as soon as the traffic grows they're all used, so there's no process available as apache is very slow in creating new forks. This is certainly increased by the fact your PHP requests seems to be quite long, they do not finish early and the apache forks are not released soon enough to treat another request. </p> <p>See on the last graphic the small amount of green before the red peak? If you could graph this on a 1 minute basis instead of 5 minutes you would see that this green amount was not big enough to take the incoming traffic without any error message.</p> <p>Now you set <code>1024</code> <code>MaxClients</code>. I guess the cacti graph are not taken after this configuration modification, because with such modification, when no more process are available, apache would continue to fork new children, with a limit of 1024 busy children. Take something like 20MB of RAM per child (or maybe you have a big memory_limit in PHP and allows something like 64MB or 256MB and theses PHP requests are really using more RAM), maybe a DB server... your server is now slowing down because you have only 768MB of RAM. Maybe when apache is trying to initiate the first 20 children you already reach the available RAM limit.</p> <p>So. a classical way of handling that is to check the amount of memory used by an apache fork (make some top commands while it is running), then find how many parallel request you can handle with this amount of RAM (that mean parallel apache children in prefork mode). Let's say it's <strong>12</strong>, for example. Put this number in apache mpm settings this way:</p> <pre><code>&lt;IfModule prefork.c&gt; StartServers 12 MinSpareServers 12 MaxSpareServers 12 MaxClients 12 MaxRequestsPerChild 300 &lt;/IfModule&gt; </code></pre> <p>That means you do not move the number of fork while traffic increase or decrease, because you always want to use all the RAM and be ready for traffic peaks. The <code>300</code> means you recyclate each fork after 300 requests, it's better than 0, it means you will not have potential memory leaks issues. MaxClients is set to 12 <strike>25 or 50 which is more than 12 to handle the <code>ListenBacklog</code> queue, which can enqueue some requests, you may take a bigger queue, but you would get some timeouts maybe</strike> (removed this strange sentende, I can't remember why I said that, if more than 12 requests are incoming the next one will be pushed in the Backlog queue, but you should set MaxClient to your targeted number of processes).</p> <p>And yes, that means you cannot handle more than 12 parallel requests.</p> <p>If you want to handle more requests:</p> <ul> <li>buy some more <strong>RAM</strong></li> <li>try to use apache in <strong>worker</strong> mode, but remove mod_php and use php as a parallel daemon with his own pooler settings (this is called <strong>php-fpm</strong>), connect it with fastcgi. Note that you will certainly need to buy some RAM to allow a big number of parallel php-fpm process, but maybe less than with mod_php</li> <li><strong>Reduce the time spent in your php process</strong>. From your cacti graphs you have to potential problems: a real traffic peak around 11:25-11:30 or some php code getting very slow. Fast requests will reduce the number of parallel requests.</li> </ul> <p>If your problem is really traffic peaks, solutions could be available with caches, like a proxy-cache server. If the problem is a random slowness in PHP then... it's an application problem, do you do some HTTP query to another site from PHP, for example?</p> <p>And finally, as stated by @Jan Vlcinsky you could try <strong>nginx</strong>, where php will only be available as <strong>php-fpm</strong>. If you cannot buy RAM and must handle a big traffic that's definitively desserve a test.</p> <p><strong>Update:</strong> About <strong>internal dummy connections</strong> (if it's your problem, but maybe not).</p> <p>Check <a href="http://wiki.apache.org/httpd/InternalDummyConnection" rel="noreferrer">this link</a> and <a href="https://stackoverflow.com/questions/4574064/serverhttp-host-not-set/4579630#4579630">this previous answer</a>. This is 'normal', but if you do not have a simple virtualhost theses requests are maybe hitting your main heavy application, generating slow http queries and preventing regular users to acces your apache processes. They are generated on graceful reload or children managment. </p> <p>If you do not have a simple basic "It works" default Virtualhost prevent theses requests on your application by some rewrites:</p> <pre><code> RewriteCond %{HTTP_USER_AGENT} ^.*internal\ dummy\ connection.*$ [NC] RewriteRule .* - [F,L] </code></pre> <p><strong>Update:</strong></p> <p>Having only one Virtualhost does not protect you from internal dummy connections, it is worst, you are sure now that theses connections are made on your unique Virtualhost. So you should really avoid side effects on your application by using the rewrite rules.</p> <p>Reading your cacti graphics, it seems your apache is not in prefork mode bug in worker mode. Run <code>httpd -l</code> or <code>apache2 -l</code> on debian, and check if you have worker.c or prefork.c. If you are in worker mode you may encounter some PHP problems in your application, but you should check the worker settings, here is an example:</p> <pre><code>&lt;IfModule worker.c&gt; StartServers 3 MaxClients 500 MinSpareThreads 75 MaxSpareThreads 250 ThreadsPerChild 25 MaxRequestsPerChild 300 &lt;/IfModule&gt; </code></pre> <p>You start 3 processes, each containing 25 threads (so 3*25=75 parallel requests available by default), you allow 75 threads doing nothing, as soon as one thread is used a new process is forked, adding 25 more threads. And when you have more than 250 threads doing nothing (10 processes) some process are killed. You must adjust theses settings with your memory. Here you allow 500 parallel process (that's 20 process of 25 threads). Your usage is maybe more: </p> <pre><code>&lt;IfModule worker.c&gt; StartServers 2 MaxClients 250 MinSpareThreads 50 MaxSpareThreads 150 ThreadsPerChild 25 MaxRequestsPerChild 300 &lt;/IfModule&gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload