PHP & Sessions: есть ли способ отключить блокировку сеанса PHP?

Есть ли способ отключить блокировку сеанса в PHP при использовании обработчика сеанса по умолчанию?

[EDIT:] Или есть, по крайней мере, способ перезапустить сеанс после вызова session_write_close() ? session_start() не работает, если какой-либо вывод уже отправлен в браузер.

Solutions Collecting From Web of "PHP & Sessions: есть ли способ отключить блокировку сеанса PHP?"

Вы не хотите его отключать … Если вы это сделаете, вы потенциально столкнетесь со множеством странных проблем, когда вы входите в систему в одном окне, выходите из системы на другом, а затем выходите в противоречивое состояние … блокировка существует по какой-то причине …

Вместо этого закройте сеанс очень рано, если вы знаете, что не собираетесь писать ему в этом запросе. После его запуска вы сможете прочитать его для всего запроса (если вы не заново запустите его или не сделаете некоторые другие специальные вещи) даже после вызова session_write_close . Итак, что бы вы сделали, это проверить запрос, чтобы увидеть, является ли это запросом на запись, а если нет, просто закройте его сразу после его открытия. Обратите внимание, что это может иметь некоторые неблагоприятные последствия, если вы позже попробуете написать сеанс (для защиты Captcha или CSRF или что-то еще), поэтому используйте с осторожностью …

Но вместо того, чтобы пытаться обойти это, я бы постарался либо сократить длины запросов (чтобы уменьшить конфликт блокировок), либо сделать cookieless запросы для тех запросов, которые не требуют сеанса вообще …

У меня была страница отчета, которая заняла более 2 минут (более 80 запросов AJAX). Я отключил сессионную блокировку до 30 секунд. Да, небеса запрещают вам удалять блокировку файлов, потому что тогда у вас есть условия гонки. И если вы не понимаете условия гонки, и вы не знаете, какой эффект будет на ваших сеансах … тогда НЕ удаляйте блокировку файлов. Однако, если вы, зная, какие данные на ваших сеансах и зная, какие условия гонки считают, считают, что нет данных, которые могут быть подвергнуты неблагоприятному воздействию условий гонки, что создаст ошибку … вы знаете, что ваша среда лучше, чем кто-то другой, так что идите на это.

MySQL, REDIS и Memcache

Также обратите внимание, что если вы переключитесь на MySQL для управления сеансом, есть вероятность 99%, ИМХО, что вы НЕ блокируете строку с момента, когда вы читали, до времени, когда вы пишете. Таким образом, используя MySQL, у вас все еще есть те же условия гонки (или проблемы с блокировкой, если вы решили заблокировать строку).

Основываясь на информации, которую я мог найти, люди, которые используют PHP Redis, используют неблокирующее приложение, которое подвержено условиям гонки … согласно следующей теме … и они приводят скорость как одну из причин, по которой им нравится эта " особенность":

https://github.com/phpredis/phpredis/issues/37

Memcached не поддерживал сессионную блокировку до версии 3.0.4 … поэтому она также была – изначально – подвержена условиям гонки.

Ясно, что с успехом этих вариантов условия гонки не являются самой большой проблемой, с которой сталкиваются программисты.

В конечном счете проблема

ВСЕ параллельные запросы ВСЕГДА будут подчиняться условиям гонки, ЕСЛИ вы блокируете блокировку, и в этот момент они не являются параллельными запросами.

Важная вещь о сеансах, блокировании и параллелизме и условиях гонки – это знать ваше приложение, знать, может ли расовое условие нарушить ваше приложение … и разработать решение, соответствующее вашему приложению. Если все, что вы делаете, это сохранить userId в сеансе и прочитать его во всех последующих запросах, вам, вероятно, не нужно беспокоиться о гоночных условиях. Если вы храните подробную историю данных, которые будут ломаться, если что-то случится не по порядку, или данные могут быть потеряны, тогда заблокируйте файл между чтением и записью и попытайтесь сделать запись как можно быстрее после чтения, насколько это возможно, чтобы ограничить время файл заблокирован.

Лучший вариант

Однако API-интерфейс без сеанса будет намного лучше для одновременных запросов. Однако, если у вас нет времени на реорганизацию такого API … тогда вы можете прочитать.

Решение Stop-Gap для хранения файлов сеансов PHP и остановки блокировки

Чтобы продолжить использование сеансов PHP по умолчанию, чтобы остановить блокировку и в основном иметь очень быстрое решение сложной проблемы, вы можете реализовать пример использования PHP-сайта SessionHandler.

У меня есть приведенный ниже код, работающий в рабочей среде для сайта с десятками тысяч подключений в минуту, и у меня еще не было проблем с условиями гонки, но я также не храню данные, которые может разорвать состояние гонки , Этот код, как я уже сказал, получил один отчет более 2 минут до менее 30 секунд … и потребовалось несколько минут для реализации. Нет схемы MySQL для создания, не Memcache или Redis для установки.

Это письмо, пример реализации, представленной в документации PHP ( http://php.net/manual/en/class.sessionhandlerinterface.php ), и он не блокирует файл сеанса при его чтении.

 <?php class MySessionHandler implements SessionHandlerInterface { private $savePath; public function open($savePath, $sessionName) { $this->savePath = $savePath; if (!is_dir($this->savePath)) { mkdir($this->savePath, 0777); } return true; } public function close() { return true; } public function read($id) { return (string)@file_get_contents("$this->savePath/sess_$id"); } public function write($id, $data) { return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; } public function destroy($id) { $file = "$this->savePath/sess_$id"; if (file_exists($file)) { unlink($file); } return true; } public function gc($maxlifetime) { foreach (glob("$this->savePath/sess_*") as $file) { if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { unlink($file); } } return true; } } 

В PHP 5.4+ использование его так же просто, как установка обработчика перед началом сеанса:

 $handler = new MySessionHandler(); session_set_save_handler($handler, true); session_start(); 

Для более низких версий PHP вы все равно можете делать это через вызовы функций … см. Документы PHP.

Вы можете перезапустить сеанс, вызвав session_start () после session_write_close (). Однако это вызовет появление нескольких малых островных развивающихся государств. Я разрешаю это, удаляя несколько SIDS из заголовка до того, как выйдет поток.

См. Этот пример: https://gist.github.com/CMCDragonkai/6912726#file-nativesession-php-L254

Кроме использования session_write_close () ? Нет, о которых я знаю.

Невозможно отключить блокировки из сеансов php. Это реальный случай использования блокировки. Только способ избавиться от сеансов и / или php. В качестве временного решения вы можете использовать обработчик сеанса riak: https://github.com/zacharyfox/riak-php-sessions он заблокирован, и он работает.

В последних версиях обработчика сеанса memcached также вводится блокировка для некоторых безумных причин и нет способа отключить его.

Если PHP не обрабатывает запросы асинхронно даже после вызова session_write_close, это может быть просто xdebug. Я не знаю, является ли это вашей проблемой, но я все время спотыкаюсь от этого и сводил меня с ума из-за этого, поэтому я решил опубликовать его, если у кого-то еще будет такая же проблема 🙂

Это довольно старый вопрос, который я обнаружил при исследовании обработчиков сеансов, однако ответ да, это возможно – но не использовать обработчик по умолчанию (без глубокого взлома в файловую систему, чтобы отключить блокировку).

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

Мое решение является частью большего расширения механизма обработки сеанса – обработчика стекируемых сеансов, который включает в себя хранилище, совместимое с обработчиком по умолчанию и (необязательно), неблокирующее чтение и запись сеанса.