Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Anmeldeversuche drosseln – PHP &MySQL &CodeIgniter

Ich habe einen Drosselmechanismus des armen Mannes implementiert in phunction Wenn ich nur APC verwende, verwende ich es folgendermaßen:

// 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));
}

Ich verwende dies auf meinem Front-Controller und übergebe den Wert an meine Routing-Methode, aber das ist eine andere Geschichte.

Das Fazit ist, dass Sie bei Verwendung von APC in der Lage sind, die Dinge sehr schnell und mit geringem Speicherverbrauch zu halten, da APC einer FILO-Methodik folgt. Wenn Sie viel höhere Timeouts benötigen, können Sie jedoch etwas in Betracht ziehen, das nicht speicherbasiert ist.

Übrigens:MySQL unterstützt Tabellen mit der MEMORY-Engine.

Das Problem mit sleep() :

Ein typischer Apache-Webserver mit installiertem PHP als Modul benötigt etwa 10 MB RAM pro Instanz. Um zu vermeiden, dass Ihr verfügbarer Arbeitsspeicher überschritten wird, gibt es einige Apache-Einstellungen, die Sie konfigurieren können, um die maximale Anzahl von Instanzen zu begrenzen, die Apache starten kann.

Das Problem ist, wenn Sie sleep() , ist diese Instanz immer noch aktiv und könnte bei genügend Anfragen alle verfügbaren Slots zum Starten neuer Server verbrauchen, wodurch Ihre Website unzugänglich wird, bis einige ausstehende Anfragen abgeschlossen sind.

Es gibt keine Möglichkeit, dies von PHP AFAIK aus zu überwinden, also liegt es am Ende an Ihnen.

Das Prinzip ist dasselbe für die systemweite Drosselung:

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;
}