Jeg implementerede en fattigmands drosselmekanisme i phunction bruger APC alene, sådan bruger jeg det:
// 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));
}
Jeg bruger dette på min Front-Controller og overfører værdien til min routingmetode, men det er en anden historie.
Den nederste linje er, at hvis du bruger APC, er du i stand til at holde tingene meget hurtigt i hukommelsen og med et lille hukommelsesforbrug, fordi APC følger en FILO-metode. Hvis du har brug for langt højere timeouts, kan du overveje at bruge noget, der dog ikke er hukommelsesbaseret.
BTW:MySQL understøtter tabeller med MEMORY-motoren.
Problemet med sleep()
:
En typisk Apache-webserver med PHP installeret som et modul vil spise omkring 10 MB RAM pr. instans, for at undgå at overskride din tilgængelige ram er der nogle Apache-indstillinger, som du kan konfigurere for at begrænse det maksimale antal forekomster, som Apache kan starte.
Problemet er, når du sleep()
, den instans er stadig aktiv og med nok anmodninger kan det ende med at spise alle de tilgængelige slots til at starte nye servere, og dermed gøre dit websted utilgængeligt, indtil nogle afventende anmodninger er gennemført.
Der er ingen måde at overvinde dette fra PHP AFAIK, så i sidste ende er det op til dig.
Princippet er det samme for system bred drosling:
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;
}