Zamrznutý požadavek při vícenásobné volání při použití session

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
khero2t
Člen | 6
+
0
-

Ahoj,
mám již delší dobu jeden podivný problém.
Mějme úplně základní aplikaci v nette např. sandbox a v ní budu používat session.
Pokud odešlu na stránku požadavek vícekrát za sebou tak mi načítání zamrzne a stránka jakoby na něco čeká a načte se až po více jak minutě.
Vícenásobný požadavek odešlu např. tak že budu na odkaz zběsile klikat třeba 10× za sebou nebo rychle mačkat F5.

pro ukázku mám např. ve startup tento kód:

<?php
public function startup(){
	sleep(1);

	$session = $this->getContext()->session;
	$namespace = $session->getSection("test");
	$namespace->prom = "test";
}
?>

V kódu je nutné mít sleep(1), aby se stránka nenačetla okamžitě, jinak bych nestihl kliknout opakovaně ještě během načítání předchozího požadavku.

Zajímavé je, že pokud místo nette session použiji klasický způsob použitím základních funkcí PHP, tak se tento problém neděje.
Tedy např:

<?php
public function startup(){
	sleep(1);

	session_start();
	$_SESSION['prom'] = "test";
	session_write_close();
}
?>

Tento případ je funkční jen pokud úplně vypnu nette session, abych mohl volat session_start();

Ještě bych upřesnil, že pokud sleduji to mé zběsilé klikání v chrome přes developer ToolBar, tak jde vidět že jak klikám tak jsou minulé požadavky canceled a ten poslední na něco čeká a dlouho se načítá.

Mnohokrát děkuji za jakoukoliv radu.

verze:
php 5.3
Nette 2.0.10
Problém se mi vyskytuje i v starších verzích Nette 2

Pro jistotu přikládám výpis nastavení session v php.ini

[Session]
session.save_handler = files
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.bug_compat42 = Off
session.bug_compat_warn = Off
session.referer_check =
session.entropy_length = 16
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5

khero2t
Člen | 6
+
0
-

Ahoj,
tak jsem si zkusil měřit části kódu, kde se aplikace zabržďuje a zjistil jsem že je to v třídě Session v metodě start();
Aplikace se zasekne při volání funkce session_start();
Pokud tedy odešlu v jeden okamžik z jednoho prohlížeče dva požadavky a jelikož není session v prvním požadavku uzavřena tak oba požadavky čekají na session_start().

Chtěl bych se zeptat, jak pracujete se session v nette?
Po uložení nebo načtení proměnné ze session vždy hned voláte $container->session->close();
A pokud někde v aplikaci bude znovu potřeba číst session tak volat $container->session->start(); ?

Dále sem si všiml že SystemContainer v metodě initialize() startuje session ještě před spuštěním aplikace. Pokud tedy nebudu v aplikaci session používat, tak je stejně hned na začátku spuštěna a takto bude spuštěna po celou dobu běhu procesu.
Bude tedy blokovat aplikaci při spuštění dalších procesů jak sem psal v diskuzi výše např. při rychlém mačkání F5 anebo rychlím klikem na jeden odkaz.

Můžete mi prosím osvětlit jak se session správně pracovat. Mnohokrát děkuji.

Majkl578
Moderator | 1364
+
0
-

Samozřejmě, to je očekávané chování. Se session může pracovat pouze jedno vlákno, ostatní čekají. Tvůj testovací kód má chybu. Aby fungoval stejně jako session od Nette, která se ti nejspíš startuje dřív, měl bys testovat následující:

protected function startup()
{
    session_start();

    sleep(1);

    $_SESSION['prom'] = "test";
    session_write_close();
}

Pak zcela jistě dojdeš ke stejnému výsledku.

Dále sem si všiml že SystemContainer v metodě initialize() startuje session ještě před spuštěním aplikace.

To se odvíjí od konfigurace (konkrétně autoStart).

khero2t
Člen | 6
+
0
-

Díky za odpověď.
To co si psal je správně. Při testování jsem si tohle vůbec neuvědomil.
Chování zamrznutí aplikace jsem ale nevysvětlil úplně správně.
Nově jsem zjistil proč to zamrzávání je tak dlouhé. Klidně i pár minut.
Jestli chování session chápu správně tak pokud jeden požadavek, který po celou dobu používá session trvá např. 2s.
Tak pokud odešlu na server např pomocí ajax v jeden omažik 3 požadavky, tak doba trvání všech požadavků by měla být 2 × 3 = 6s. Tedy díky zamčené session prvního požadavku ty ostatní čekají než se odemče.
Aplikace se ale na serveru chová tak že doba vykonávání trvá 30 × 3 = 90s
session_start() čeká na něco neobvikle dlouho.
Shodou okolností je 30s maximální doba běhu procesu nastavená na serveru. Náhoda?
Proto mě blokování krátce běžících požadavků tak dlouhou dobu zmátlo a hledal jsem chybu jinde.
Problém ale asi nebude s špatnou prací se session ale v podivném chování serveru.
Kdyby se náhodou někdo s něčím takovým už setkal, budu rád za každou radu.
Díky

revoke
Člen | 36
+
0
-

Ahoj, přišel jsi na něco nového? Teď jsem spustil svou aplikaci na produkční verzi a ta čas od času podobným způsobem zamrzne, což je velmi nepříjemné. Pravidelně to dělá u našeptávače, což napovídá tvému postřehu, že se tak děje u „slepených“ požadavků. Nastavení nižší hodnoty time_limit (aktuálně na 3sec) zkrátí dobu zamrznutí, ale i tak jsou to minuty čekání, což se na produkčním server trochu blbě ladí :-/ Když dojde k zatuhnutí, jde stránka spustit v jiném prohlížeči.

Resp. nemáte někdo tip, jak takové chování odladit?

Nette Framework version 2.0.8

khero2t
Člen | 6
+
0
-

Ahoj.
Problem jsem nakonec nasel. Nejsem zkuseny spravce serveru tak to mozna nebude uplne presny popis, ale problem byl tento.
Nas server ma svuj disk na kterem je nainstalovany linux a apache. Veskera data webu se ale nachazi na externim NAS disku. To znamena se docasne tempy ktere se vytvari pro uchovani session se ukladali take na tento externi disk. Tato komunikace byla zrejmne problematicka tak to vytvarelo neocekavane chovani. Jakmile sem v nette nastavil ukladani session na disk, kde je umisteny apache tak problem zmizel. Problemy take vznikaly pri vytvare cache nette. Pri presmerovani na stejny disk se problem vyresil.
Nevim jestli se jednalo o spatne technicke reseni serveru nebo nastaveni apache, ale v mem pripade to bylo reseni problemy. Vyse popsana nutnost uzavreni session pak nebyla vubec nutna.