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

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

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

Результаты профилирования xdebugger

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

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

 session.gc-probability = 0 

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

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

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

См. Здесь: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

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

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

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

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

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

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

Один из способов избежать этой проблемы – попросить 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(); 

КОНЕЦ.

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

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

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

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

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