Ho implementato un meccanismo di limitazione dei poveri in funzione usando solo APC, ecco come lo uso:
// 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));
}
Lo uso sul mio Front-Controller e passo il valore al mio metodo di routing, ma questa è un'altra storia.
La linea di fondo è che se usi APC sei in grado di mantenere le cose molto velocemente in memoria e con un consumo di memoria ridotto perché APC segue una metodologia FILO. Se hai bisogno di timeout molto più alti, potresti prendere in considerazione l'utilizzo di qualcosa che non è basato sulla memoria.
A proposito:MySQL supporta le tabelle con il motore MEMORY.
Il problema con sleep()
:
Un tipico server Web Apache con PHP installato come modulo consumerà circa 10 MB di RAM per istanza, per evitare di superare la RAM disponibile ci sono alcune impostazioni di Apache che puoi configurare per limitare il numero massimo di istanze che Apache è in grado di avviare.
Il problema è quando sleep()
, quell'istanza è ancora attiva e con un numero sufficiente di richieste potrebbe finire per consumare tutti gli slot disponibili per avviare nuovi server, rendendo così il tuo sito web inaccessibile fino al completamento di alcune richieste in sospeso.
Non c'è modo di superare questo problema da PHP AFAIK, quindi alla fine tocca a te.
Il principio è lo stesso per la limitazione a livello di sistema:
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;
}