Ik heb een poor-man's throttling-mechanisme geïmplementeerd in phunction alleen APC gebruik, dit is hoe ik het gebruik:
// allow 60 requests every 30 seconds
// each request counts as 1 (expensive operations can use higher values)
// keep track of IPs by REMOTE_ADDR (ignore others)
$throttle = ph()->Throttle($ttl = 30, $exit = 60, $count = 1, $proxy = false);
if ($throttle === true)
{
// IP exceded 30 requests in the last 60 seconds, die() here
}
else
{
// $throttle is a float
// number of requests in the last 30 seconds / 30 seconds
/*
1 req / 30 = 0,033 sec
5 req / 30 = 0,166 sec
10 req / 30 = 0,333 sec
15 req / 30 = 0,5 sec
20 req / 30 = 0,666 sec
25 req / 30 = 0,833 sec
30 req / 30 = 1 sec
*/
usleep(intval(floatval($throttle) * 1000000));
}
Ik gebruik dit op mijn Front-Controller en geef de waarde door aan mijn routeringsmethode, maar dat is een ander verhaal.
Het komt erop neer dat als je APC gebruikt, je dingen heel snel in het geheugen kunt houden en met weinig geheugenverbruik, omdat APC een FILO-methodologie volgt. Als je veel hogere time-outs nodig hebt, kun je overwegen iets te gebruiken dat niet op het geheugen is gebaseerd.
Tussen haakjes:MySQL ondersteunt tabellen met de MEMORY engine.
Het probleem met sleep()
:
Een typische Apache-webserver waarop PHP als module is geïnstalleerd, verbruikt ongeveer 10 MB RAM per instantie. Om te voorkomen dat u uw beschikbare RAM-geheugen overschrijdt, zijn er enkele Apache-instellingen die u kunt configureren om het maximale aantal instanties te beperken dat Apache kan starten.
Het probleem is wanneer je sleep()
, die instantie is nog steeds actief en kan met voldoende verzoeken alle beschikbare slots opslokken om nieuwe servers te starten, waardoor uw website ontoegankelijk wordt totdat enkele lopende verzoeken zijn voltooid.
Er is geen manier om dit met PHP AFAIK te verhelpen, dus uiteindelijk is het aan jou.
Het principe is hetzelfde voor systeembrede beperking:
function systemWide($ttl = 86400, $exit = 360)
{
if (extension_loaded('apc') === true)
{
$key = array(__FUNCTION__);
if (apc_exists(__FUNCTION__) !== true)
{
apc_store(__FUNCTION__, 0, $ttl);
}
$result = apc_inc(__FUNCTION__, 1);
if ($result < $exit)
{
return ($result / $ttl);
}
return true;
}
return false;
}