Подтвердить что ты не робот

Session_start() занимает ОЧЕНЬ ДЛИННОЕ ВРЕМЯ

Сайт Mys работает очень медленно (и я не имел никакого представления о том, почему). Он основан на приложении Zend, я использовал около десятков таких сайтов, поэтому я уверен, что MY-код в порядке.

Я установил xdebugger на сервер, попытался профилировать его и угадать, что? php:: session_start() заняло 48.675 секунд. Четвертое восемь с половиной секунд! Это невероятно! Что может быть причиной этого? Это обычная операция, почему она может выполнить SO long? Как исправить такое поведение, которое настраивает для редактирования? Искал через Google, но не нашел хорошего ответа (почти везде есть вопрос, но ответа нет). Спасибо прежде!

xdebugger profiling results

4b9b3361

Ответ 1

Мое предположение - это процедура сбора мусора, которая запускается внутри встроенной функции session_start(). Возможно, вы сделали что-то, что хранит много старых файлов сеансов, например, изменило максимальное время жизни? Или, может быть, вы решили, что было бы неплохо хранить их в базе данных, но забыл создать подходящий индекс? Собственный GC файл stat() для каждого файла сеанса для проверки на истечение срока действия. Это занимает много времени, если есть много файлов.

изменить. Чтобы помочь вам только для отладки, отключите сбор мусора, временно установив session.gc-probability:

session.gc-probability = 0

Убедитесь, что настройки установлены, я не знаю, что может сделать здесь структура zend.

P.S. Трудно предположить исправить, не зная причину. Мой ответ призван помочь вам определить причину.

Ответ 2

session_start (с сеансами, хранящимися в файлах) блокируется в PHP, поэтому эта проблема возникает, если вы попытаетесь запустить несколько сеансов сервера для того же сеанса браузера (AJAX или несколько вкладок/окон браузера). Каждый session_start будет ждать, пока остальные сеансы не будут закрыты.

Смотрите здесь: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

Попробуйте перейти от файлов к хранилищу данных в хранилищах.

Ответ 3

У меня была эта проблема, и я удивлен, что никто не опубликовал этот конкретный ответ. Возможно, это не так, но стоит проверить.

PHP ЗАПИСЫВАЕТ ФАЙЛ СЕССИИ во время обработки страницы, чтобы страница имела эксклюзивный доступ к ней. Подумайте об этом, файл sess_184c9aciqoc не является базой данных, поэтому два вызова в одном сеансе не могут получить к нему доступ одновременно. Поэтому, если у вас много вызовов ajax, вы можете получить "пробку". После того, как вы начнете выполнять расширенные скрипты, это нужно, чтобы остерегаться. Кстати, вот функция для хранения массива временных меток. Я использовал это, чтобы понять, что начало сеанса было виновником:

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

тогда я вызываю следующее:

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

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

Надеюсь, что это будет полезно!

Ответ 4

Другой подход может заключаться в том, что вы установили большой memory_limit в PHP.ini.

Я сделал это для загрузки огромных дампов mysql в PHPMyAdmin и загрузки времени spiked, возможно (как было сказано выше) много файлов сеансов, сложенных сейчас, когда у PHP было достаточно места. По умолчанию это 128M. Я сделал это в четыре раза.

Ответ 5

Один из способов избежать этой проблемы - попросить PHP хранить сеансы в таблице базы данных вместо файлов.

Во-первых, я дам вам несколько ссылок в качестве реальных кредитов для этого решения:

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/

Тогда реализация кода I, полученная из этих чтений:

<?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();

END.

Ответ 6

Если у вас несколько одновременных вызовов ajax на одной странице, эта ситуация может вызвать вашу проблему.

Ответ 7

В моем случае это были неправильные настройки сервера memcache в /etc/php.d/memcached.ini Здесь - информация о свойствах memcache и здесь, как для настройки хранилища в memcache.

Ответ 8

У меня была эта проблема. session_start занимал около 5 секунд.

Моя проблема заключалась в том, что я указал некоторые переменные выше.

Я переместил session_start в начало и теперь требуется несколько миллисекунд.