it-swarm.com.de

session_start () dauert sehr lange

Meine Website arbeitet sehr langsam (und ich hatte keine Ahnung, warum). Es basiert auf Zend Application, ich habe ungefähr zehn solcher Sites gemacht, daher bin ich sicher, dass MEIN Code in Ordnung ist.

Ich habe xdebugger auf dem Server installiert, habe versucht zu profilieren und weißt du was? php :: session_start () dauerte 48,675 Sekunden. Achtundvierzig Sekunden! Es ist unglaublich! Was könnte der Grund dafür sein? Es ist eine gewöhnliche Operation, warum könnte es SO lange ausgeführt werden? Wie lässt sich ein solches Verhalten beheben, welche Konfigs müssen bearbeitet werden? Über Google gesucht, aber keine gute Antwort gefunden (fast überall gibt es eine Frage, aber keine Antwort). Danke schon mal!

xdebugger profiling results

21
ABTOMAT

Meine Vermutung wäre die Müllsammelroutine, die in der nativen Funktion session_start() ausgeführt wird. Vielleicht haben Sie etwas getan, das viele alte Sitzungsdateien enthält, z. B. die maximale Lebensdauer. Oder vielleicht haben Sie entschieden, es wäre eine gute Idee, sie in einer Datenbank zu speichern, haben aber vergessen, einen geeigneten Index zu erstellen? Die native GC-Routine stat () überprüft jede einzelne Sitzungsdatei auf Ablauf. Dies ist zeitaufwändig, wenn viele Dateien erstellt werden.

edit : um Ihnen zu helfen nur zum Debuggen , deaktivieren Sie die Garbage Collection, indem Sie session.gc-wahrscheinlichkeit vorübergehend setzen

session.gc-probability = 0

Stellen Sie sicher, dass die Einstellungen eingehalten werden. Ich weiß nicht, was das Zend-Framework hier tun könnte.

P.S. Es ist schwierig, eine Lösung vorzuschlagen, ohne die Ursache zu kennen. Meine Antwort soll Sie zur Ermittlung der Ursache führen.

19
goat

session_start (mit in Dateien gespeicherten Sitzungen) wird in PHP blockiert. Wenn Sie also versuchen, mehrere Serversitzungen für dieselbe Browsersitzung (AJAX oder mehrere Browser-Registerkarten/Fenster) zu starten, tritt dieses Problem auf. Jeder session_start wartet, bis die anderen Sitzungen beendet sind.

Siehe hier: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

Versuchen Sie, von Dateien zu Datenbankspeicher für Sitzungen zu wechseln.

18

Ich hatte dieses Problem und bin überrascht, dass niemand diese konkrete Antwort gepostet hat. Es kann nicht so sein, aber es lohnt sich zu prüfen.

PHP LOCKT DIE SITZUNGSDATEI, während eine Seite verarbeitet wird, sodass diese Seite exklusiven Zugriff darauf haben kann. Denken Sie darüber nach, die Datei sess_184c9aciqoc ist keine Datenbank. Daher können zwei Aufrufe in derselben Sitzung nicht gleichzeitig darauf zugreifen. Wenn Sie also viele Ajax-Anrufe haben, können Sie einen "Stau" bekommen. Sobald Sie mit dem fortgeschrittenen Scripting beginnen, müssen Sie sich davor hüten. Im Übrigen gibt es hier eine Funktion zum Speichern eines Arrays von Zeitstempeln. Ich benutzte das, um herauszufinden, ob der Start der Sitzung der Schuldige war:

//time function for benchmarking
if( function_exists('gmicrotime')){
    function gmicrotime($n=''){
        #version 1.1, 2007-05-09
        //store array of all calls
        global $mT;
        list($usec, $sec) = explode(' ',microtime());
        if(!isset($mT['_base_']))$mT['_base_']=$sec;
    $t=round((float)$usec + (float)(substr($sec,-4)),6);
    $mT['all'][]=$t;
    if($n){
        if(isset($mT['indexed'][$n])){
            //store repeated calls with same index.  If in a loop, add a $i if needed
            if(is_array($mT['indexed'][$n])){
                $mT['indexed'][$n][]=$t;
            }else{
                $mT['indexed'][$n]=array($mT['indexed'][$n],$t);
            }
        }else $mT['indexed'][$n]=$t;    
    }
    //return elapsed since last call (in the local array)
    $u=$mT['all'];
    if(count($u)>1){
        $mT['_total_']=$u[count($u)-1] - $u[0];
        return round(1000*($u[count($u)-1]-$u[count($u)-2]),6);
    }
}
gmicrotime('pageStart');
}

dann rufe ich wie folgt an:

gmicrotime('beforeSessionStart');
session_start();
gmicrotime('afterSessionStart');

do_something_slow();
gmicrotime('afterSlowProcess');
//etc..
echo '<pre>';
print_r($mT);  

Hoffe das ist hilfreich!

5
Samuel Fullman

Ein anderer Ansatz könnte sein, dass Sie in PHP.ini einen großen memory_limit gesetzt haben.

Ich habe das getan, um riesige Mysql-Dumps in PHPMyAdmin hochzuladen und die Ladezeit zu erhöhen, vielleicht (wie oben gesagt) viele Sitzungsdateien angehäuft, da PHP jetzt Platz hat. Der Standardwert ist 128M, denke ich. Ich hatte das vervierfacht.

2
PeerBr

Wenn Sie gleichzeitig mehrere Ajax-Anrufe auf derselben Seite haben, kann dies zu einem Problem führen.

0
Nicolas Finelli

Ich hatte gerade dieses Problem. session_start dauerte etwa 5 Sekunden.

Mein Problem war, dass ich einige Variablen darüber deklariert hatte. 

Ich habe session_start nach oben verschoben und es dauert jetzt ein paar Millisekunden.

0
Shane Zammit

In meinem Fall handelte es sich um falsche Memcache-Server-Einstellungen in /etc/php.d/memcached.iniHier sind Informationen zu Memcache-Eigenschaften und hier wie wird der Speicher im Memcache eingerichtet.

0
vikramaditya234

Eine Möglichkeit, dieses Problem zu vermeiden, besteht darin, PHP zu bitten, Sitzungen in einer Datenbanktabelle anstelle von Dateien zu speichern.

Zunächst werde ich Ihnen einige Links als echte Credits für diese Lösung geben:

http://www.tonymarston.net/php-mysql/session-handler.html

http://shiflett.org/articles/storing-sessions-in-a-database

http://culttt.com/2013/02/04/how-to-save-php-sessions-to-a-database/

Dann eine Code-Implementierung, die ich aus diesen Lesungen ableitete:

<?php

class TLB_Sessions_in_Database
{
    private $debug;
    private $dbc;

    function __construct()
    {
        $this->debug = false;

        session_set_save_handler(
            array($this, '_open'),
            array($this, '_close'),
            array($this, '_read'),
            array($this, '_write'),
            array($this, '_destroy'),
            array($this, '_clean')
        );
    }

    function _open()
    {
        if( $this->debug ) echo '_open:'.PHP_EOL;

        if( ($this->dbc = mysql_connect(DB_Host, DB_USER, DB_PASSWORD)) !== false )
        {
            $select_db = mysql_select_db(DB_NAME, $this->dbc);
            $set_charset = mysql_set_charset(DB_CHARSET, $this->dbc);

            if( $this->debug ) echo '- return: '.(( $select_db && $set_charset ) ? 'true' : 'false').PHP_EOL;

            return( $select_db && $set_charset );
        }
        else
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( false );
    }

    function _close()
    {
        if( $this->debug ) echo '_close:'.PHP_EOL;

        return( mysql_close($this->dbc) );
    }

    function _read($session_id)
    {
        if( $this->debug ) echo '_read:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);

        $sql = "SELECT `session_data` FROM `".DB_NAME."`.`php_sessions` WHERE `session_id` = '".$session_id."'";

        if( $this->debug ) echo '- query: '.$sql.PHP_EOL;

        if( ($result = mysql_query($sql, $this->dbc)) !== false )
        {
            if( !in_array(mysql_num_rows($result), array(0, false), true) )
            {
                $record = mysql_fetch_assoc($result);

                return( $record['session_data'] );
            }
        }
        else
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( '' );
    }

    function _write($session_id, $session_data)
    {
        if( $this->debug ) echo '_write:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);
        $session_data = mysql_real_escape_string($session_data);

        //$sql = "REPLACE INTO `php_sessions` (`session_id`, `last_updated`, `session_data`) VALUES ('".$session_id."', '".time()."', '".$session_data."')";
        $sql = "INSERT INTO `".DB_NAME."`.`php_sessions` (`session_id`, `date_created`, `session_data`) VALUES ('".$session_id."', NOW(), '".$session_data."') ON DUPLICATE KEY UPDATE `last_updated` = NOW(), `session_data` = '".$session_data."'";

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }

    function _destroy($session_id)
    {
        if( $this->debug ) echo '_destroy:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);

        $sql = "DELETE FROM `".DB_NAME."`.`php_sessions` WHERE `session_id` = '".$session_id."'";

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }

    function _clean($max)
    {
        if( $this->debug ) echo '_clean:'.PHP_EOL;

        $sql = 'DELETE FROM `'.DB_NAME.'`.`php_sessions` WHERE `last_updated` < DATE_SUB(NOW(), INTERVAL '.$max.' SECOND)';

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }
}

new TLB_Sessions_in_Database();

ENDE.

0