2014-09-24 16 views
6

NB To jest nie duplikat PHP session_start() causing HTTP requests to hang (i inne podobnie nazwane pytania na SO), ponieważ moje zawieszenie jest sporadyczne, a nie stałe.Dlaczego PHP czasami zawiesza się na session_start()

Korzystanie z Ubuntu 12.04,Magento, PHP-FPM (5.4) i domyślnej sesji sesji PHP (z plikami na ext4).

Nawiasem mówiąc (once per month) wszystkie procesy PHP powiesić na session_start() (zgodnie z FPM-slow.log):

[24-Sep-2014 11:03:04] [pool www] pid 24259 
script_filename = /data/web/public/index.php 
[0x00007f00b4ec6480] session_start() /data/web/public/includes/src/__default.php:7687 
[0x00007f00b4ec6130] start() /data/web/public/includes/src/__default.php:7730 
[0x00007f00b4ec5fb8] init() /data/web/public/includes/src/__default.php:8086 
[0x00007f00b4ec5e30] init() /data/web/public/includes/src/__default.php:33902 
[0x00007f00b4ec5bd0] __construct() /data/web/public/includes/src/__default.php:23841 
[0x00007f00b4ec5ae8] getModelInstance() /data/web/public/app/Mage.php:463 
[0x00007f00b4ec59c8] getModel() /data/web/public/app/Mage.php:477 
[0x00007f00b4ec49a0] getSingleton() /data/web/public/includes/src/__default.php:14044 
[0x00007f00b4ec4848] preDispatch() /data/web/public/includes/src/Mage_Adminhtml_Controller_Action.php:160 
[0x00007f00b4ec3b00] preDispatch() /data/web/public/includes/src/__default.php:13958 
[0x00007f00b4ec26e0] dispatch() /data/web/public/includes/src/__default.php:18331 
[0x00007f00b4ec20c0] match() /data/web/public/includes/src/__default.php:17865 
[0x00007f00b4ec1a98] dispatch() /data/web/public/includes/src/__default.php:20465 
[0x00007f00b4ec1908] run() /data/web/public/app/Mage.php:684 
[0x00007f00b4ec17f8] run() /data/web/public/index.php:87 

lsof mówi:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME 
php5-fpm 24259 app 10uW REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 
php5-fpm 24262 app 10u REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 
php5-fpm 24351 app 10u REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 
php5-fpm 24357 app 10u REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 
php5-fpm 24358 app 10u REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 
php5-fpm 25563 app 10u REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 
php5-fpm 25564 app 10u REG 202,1 82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6 

Według strace wszystkie te procesy czekają na stadzie (LOCK_EX), nawet ten, który ma flagę W w powyższym wyjściu lsof.

Użycie procesora podczas tego incydentu jest blisko 0.

Więc dlaczego pierwszy session_start hang, choć wydaje się, że nabył blokady zapisu na plik sesji? Jak mogę to debugować?

Oto dyskusja pod tytułem "race condition with ajax and php sessions". W rzeczywistości żądania, które wyzwalają powyższy problem, są niezmiennie wywołaniami AJAX. Jednak ten artykuł stanowi, że:

Jeśli używany wbudowany, domyślny sesji PHP magazynowe (który używa plików), nigdy nie natknąć się na problem.

Obecnie nie mam pojęcia, gdzie szukać dalej.

+1

Zanim zacznę myśleć: cholernie dobre pytanie! edytuj: Po zastanowieniu: Nie mam pojęcia. – MoshMage

+1

Raz w miesiącu? Czy zdarza się regularnie, mniej więcej w tym samym dniu i czasie? –

+0

Zły dysk? To będzie trudne do debugowania. – Brad

Odpowiedz

0

Przy twoich wywołaniach Ajax Zgaduję, że w tym pliku masz session_start i gdzieś w twoim katalogu/tmp w twoim ubuntu php zapisuje swoje sesje. Aby rozwiązać problem, musisz uruchomić testowanie obciążenia na tych skryptach, może to być także db, który może być czynnikiem, którego nie widać gołym okiem.

Spróbuj czegoś takiego: http://smartbear.com/products/qa-tools/load-testing-tool/ajax-load-testing/ jako próba, możesz dojść do sedna problemu. Musisz także głębiej zagłębić się w sesje w tej sprawie, w tym te pojedyncze pliki, które używają wywołań ajaxowych.

Powinieneś skonfigurować testowanie wydajności na podstawie tych wywołań, które można uruchomić, gdy wystąpi problem. Warstwy to PHP, PHP-FPM, Magento, Im zgadywanie MySQL, Ubuntu, połączenie sieciowe i Apache?

+0

również spójrz na to: http://smartbear.com/products/qa-tools/load-testing-tool/load-testing-metrics/ potrzebujesz narzędzi i pewnego rodzaju danych do porównania – unixmiah

0

Jeśli masz skrypt importu, który trwa długo, przeglądarka wydaje się blokować i nie możesz już uzyskać dostępu do witryny. dzieje się tak, ponieważ żądanie odczytuje i blokuje plik sesji, aby zapobiec uszkodzeniu.

można albo - użyć innego programu obsługi sesji z session_set_save_handler() - wykorzystanie session_write_close() w skrypcie importowej tak szybko nie trzeba już sesji (najlepszy moment jest tuż przed długim czasie część odbywa) , możesz session_start kiedy chcesz i ile razy chcesz, jeśli twój skrypt importu wymaga zmiany zmiennych sesji.

http://php.net/manual/en/function.session-start.php

0

radziłbym, by sprawdzić tabeli sesji na Magento ... ponieważ przechowuje sesje w tabeli mysql może masz problem ze swoim db ...

0

go znaleźć najlepszy do przechowywania sesji na dysku lokalnym, a nie w bazie danych.

Utwórz katalog o nazwie „Sesje” w katalogu głównym, a następnie mieć wszystkie sesje napisać tam umieszczając poniższy kod na górze skrypty tuż przed nazywają „session_start()”

$session_path = $_SERVER['DOCUMENT_ROOT']; //this session path assumes you are not using a subdomain 
ini_set('session.save_path', $session_path.'/sessions/'); 

Ładowanie z pliku jest szybsze niż ładowanie z bazy danych. A php zarządza tym samym, więc wybieram szybkość.

1

Coś nieznanego blokuje pierwszy skrypt i blokuje pozostałe.

PHP utrzymuje, że plik sesji jest otwarty do zapisu, dopóki skrypt nie zostanie zakończony. Oznacza to, że jeśli skrypt utknie lub zostanie przyłapany na robieniu czegoś powolnego, wszystkie inne żądania zależne od sesji będą blokowane, dopóki się nie zakończy.

Dwie najlepsze praktyki - nie uruchamiaj sesji, dopóki jej nie potrzebujesz, i jawnie zakończ sesję sesją session_write_close(), gdy skończysz ją zmieniać, szczególnie przed zrobieniem czegoś powolnego lub potencjalnie błędnego.

Wówczas utworzy się tylko jeden zablokowany proces zamiast zablokowanego użytkownika.

0

Dobrą praktyką jest zainstalowanie memecached dla php i po prostu ustawić te wartości:

session.save_handler = memcache 
session.save_path = “tcp://127.0.0.1:11211″ 
Powiązane problemy