ugrás a tartalomhoz

SESSION eltünedezik.

gtoma · 2011. Szep. 6. (K), 16.02
Sziasztok!

Elég sokat használok AJAX technológiát, és rendszeresen visszatér egy probléma.
PHP val mentek sessinba adatokat, és néha, a doom betöltődése utáni közvetlen ajax lekérést kezelő PHP nem látja a sessiont.

Példa:
printelem ezt:
  1. $_SESSION['labda'] = 52;  
  2.   
  3. print "  
  4. <script>  
  5. ajaxlekeres();  
  6. </script>  
  7. "  
Ez mondjuk a JS:
  1. function ajaxlekeres() {  
  2.     var BaseURL = 'server.php';  
  3.     var myPars      = 'com='+comok+'&rnd='+this.RND;  
  4.     var myAjax = new Ajax.Request( BaseURL, {  
  5.                 parameters: myPars,  
  6.                 onComplete: FrissitesUpdate  
  7.     });  
  8. }  
  9. function FrissitesUpdate(originalRequest) {  
  10.     $('target').innerHTML = originalRequest.responseText;  
  11. }  
server.php:
  1. print $_SESSION['labda';  
Ez persze csak egy példa. Az elv a lényeges.
Hogy néha, ilyenkor a server.php "elveszti" a sessiont.
Persze nem mindig.

Elképzelni sem tudom, hogy mi lehet a probléma hátterében.

A rendszer amit használok elég sokszor dolgozik ajax megoldással. (prototype)
Valakitől hallottam, hogy csak x db ajax lekérés futhat egy időben. Lehet esetleg ez a probléma, de akkor miért KEZELŐDIK a lekérés, és miért csak a
session tűnik el?
Miért "instabilitás" a jellemző a dologra, ahelyett, hogy egyszerűen nem működne?

Már párszor találkoztam ezzel a problémával, de sajnos még senki nem tudott választ adni a miértre.

Tudom, hogy ez a kérdés nem csak php témába tartozik, azért raktam ide, mert a fő tünet php-re vonatkozik.
 
1

a doom betöltődése utáni

Poetro · 2011. Szep. 6. (K), 16.48
a doom betöltődése utáni közvetlen ajax lekérést kezelő PHP nem látja a sessiont.

Milyen doom betöltődése után? Valami 90-es évekbeli játékot indítasz? Hogyan van beállítva a PHP session kezelése?
2

DOMReady event

szeber · 2011. Szep. 6. (K), 16.56
Ha jol sejtem doom alatt DOM-ot ertesz, illetve feltetelezem mindket php scriptedben a session kezelese elott van egy session_start() fuggvenyhivas.

A HTML feldolgozasa soran, ha a bongeszo megkapta a </script> tag-et, es eljutott a <script> tag-ig, elkezdi a JS ertelmezeset. A te peldakodod tehat egybol elkuldi az AJAX kerest a szervernek, meg mielott az oldalt eloallito PHP scripted veget ert volna. A session adatok lemezre irasat a PHP nem a $_SESSION szuperglobal-ba iraskor vegzi, hanem a script futasanak a vegen.

Ha meg nem volt kiirva a session, akkor nem lesznek benne az adatok (es valoszinuleg meg jol felul is fogja irni a session-odet az ujonnan letrejott session). Az, hogy neha mukodik, neha nem azert van, mert neha elobb vegeter a script futasa, mint hogy beerkezne az AJAX-os keresed, neha meg nem (pl kliens gep, vagy halozat leterheltsegetol fuggoen).

Tehat kesleltetned kene az ajax keresek kikuldeset a DOMReady vagy DOMLoad esemenyig. Lasd <body> tag onload parametere vagy (inkabb ez a javasolt) az ajax lib-ed esemenykezeloje.
3

Igen, ez megmagyarázhatja

gtoma · 2011. Szep. 6. (K), 17.31
Jól látod, doom alatt nem a játékot értettem, hanem elírtam a dom-ot. :) A példakód sajnos rossz volt, de reménykedtem benne, hogy érthető az elv, és látszik, hogy Te megértetted.

Természetesen minden alap megvan. Azonban [quote]A session adatok lemezre irasat a PHP nem a $_SESSION szuperglobal-ba iraskor vegzi, hanem a script futasanak a vegen.[quote] egy lehetséges probléma.

Picit módosítottam a kódon, beraktam egy 1 mp-s késleltetést, úgy tűnik így nem hibázik. (Vagyis hibázik egy helyen, de ott megint csak az általad vázolt probléma lehet a ludas. egyszerre több alkalommal hívok meg egy php-t ami sessionba számokat ment, van amelyik hibázik, és van amelyik nem. chaptát csinálok... )

Azt hiszem, módosítok a kódon, hogy biztosan ne akadjon össze a futás.

Köszönöm.

Egyébiránt tudsz olyan korlátozásról, hogy csak x db ajax lekérés futhat egyszerre?
4

Egyébiránt tudsz olyan

Poetro · 2011. Szep. 6. (K), 17.37
Egyébiránt tudsz olyan korlátozásról, hogy csak x db ajax lekérés futhat egyszerre?

A Browserscope oldalon nézd meg a Connections per Hostname oszlopot, de a legjobb, ha azonos domén névre maximum csak 2 párhuzamos kérést intézel.
6

Ez a race condition bug,

bb0072 · 2011. Szep. 6. (K), 18.08
Ez a race condition bug, amibe már évek óta nem futottam bele, mégpedig azért, mert már javították. A php standard session kezelőjével tudomásom szerint nem is fordult elő soha, de például a memcached-es sessionkezelésnek volt egy ilyen bugja még anno.

Az tévedés, hogy a php requestek egymásra indulnak a fenti esetben. A php-nak úgy kell viselkednie, hogy a párhuzamos szálat addig nem indítja el, amíg az eredeti ki nem írta a session-t (praktikusan ez akkor történik, mikor a script véget ér, feltéve, hogy nem volt session_write_close hívás). Erre több tesztet is futtattam annak idején, hacsak azóta vissza nem tért a hiba, akkor így kell lennie.

Azt kéne megnézned, hogy mi a session kezelőd, (ha nem a standard, akkor annak a verziószáma), illetve milyen verziójú php fut nálad.

Illetve futtathatsz tesztet úgy, hogy a main szálba, a végén teszel pl. egy flush()-t és egy sleep(10)-et, ettől biztosan elindul az ajax hívás, mielőtt véget érne a szál. Firebuggal láthatod, hogy melyik folyamat mikor indult. Ha a requestek egymásra indulnak, akkor gáz van, valószínűleg php-t kell frissíteni a szerveren.
8

OPS!

gtoma · 2011. Szep. 6. (K), 18.15
A php 5.2.17

Session:
Ez van a rendszerbe építve:
  1. session_module_name("user");  
  2.   
  3. function session_open($path$name) {  
  4.    return(true);  
  5. }  
  6.   
  7. function session_close() {  
  8.    return(true);  
  9. }  
  10.   
  11. function session_read($id) {  
  12.     global $DB_HOSTNAME$DB_FELHNEV$DB_PASSWORD;  
  13.     $DB_CONNECT = ConnectDatabase();  
  14.     $sql = "select * from session where id='" . $id . "'";  
  15.     $result = mysql_query($sql$DB_CONNECT);  
  16.     $row = mysql_fetch_assoc($result);  
  17.     mysql_close($DB_CONNECT);  
  18.     return($row["data"]);  
  19. }  
  20.   
  21. function session_write($id$data) {  
  22.     global $DB_HOSTNAME$DB_FELHNEV$DB_PASSWORD;  
  23.     $DB_CONNECT = ConnectDatabase();  
  24.     $sql = "update session set data = '" . addslashes($data) . "' , user='', time='".date("Y-m-d H:i:s")."' where id='" . $id . "'";  
  25.     mysql_query($sql$DB_CONNECT);  
  26.     if(mysql_affected_rows()) {  
  27.         mysql_close($DB_CONNECT);  
  28.         return(true);  
  29.     }  
  30.     $sql = "insert session set data = '" . addslashes($data) . "', id='" . $id . "'";  
  31.     mysql_query($sql$DB_CONNECT);  
  32.     mysql_close($DB_CONNECT);  
  33.     return(true);  
  34. }  
  35.   
  36. function session_remove($id) {  
  37.     global $DB_HOSTNAME$DB_FELHNEV$DB_PASSWORD;  
  38.     $DB_CONNECT = ConnectDatabase();  
  39.     $sql = "delete session where id='" . $id . "'";  
  40.     mysql_query($sql$DB_CONNECT);  
  41.     mysql_close($DB_CONNECT);  
  42.     return(true);  
  43. }  
  44.   
  45. function session_gc() {  
  46.     global $DB_HOSTNAME$DB_FELHNEV$DB_PASSWORD;  
  47.     $DB_CONNECT = ConnectDatabase();  
  48.     $life = (24*60*60);  
  49.     $sql = "delete from session where time < '" . date("Y-m-d H:i:s", time() - $life) . "'";  
  50.     mysql_query($sql$DB_CONNECT);  
  51.     mysql_close($DB_CONNECT);  
  52.     return(true);  
  53. }  
  54.   
  55. session_set_save_handler("session_open""session_close",  
  56.    "session_read""session_write""session_remove""session_gc");  
11

igen, nincs lockolas a

Tyrael · 2011. Szep. 6. (K), 19.44
igen, nincs lockolas a kododban, a read-be kellene lockolnod vagy az adott id-ju rekordot(innodb tamogatja, myisam nem) tranzakcioval pl., vagy ha ez nem tamogatott, akkor a session tablaba fel lehetne venni egy locked oszlopot, es az openbol futtatsz egy ilyesmi queryt:
update session set locked = 1 where id = $id and locked = 0;
ezutan megnezed az affected_rows-bol, hogy sikerult-e lockolni.
ha igen, akkor mehetsz tovabb, ha nem, akkor sleep(), majd ujraprobalsz(egy ido utan azert timeoutolj...).

Tyrael
9

Kb. az idok kezdete ota van

Tyrael · 2011. Szep. 6. (K), 19.38
Kb. az idok kezdete ota van lockolas a beepitett session kezeloben:
http://svn.php.net/viewvc/php/php-src/trunk/ext/session/mod_files.c?revision=9421&view=markup#l90
sajnos a dokumentacioban nem nagyon esik errol emlites (nyitottam neki egy bugreportot: https://bugs.php.net/bug.php?id=55624 ha nagyon nem oldja meg senki, akkor majd kijavitom en).

ha jol emlekszem, akkor nem a memcached, hanem a memcache futott bele ebbe a problemaba:
http://pecl.php.net/package-info.php?package=memcache&version=3.0.4

Tyrael
5

Nálunk is előfordult párszor

Hidvégi Gábor · 2011. Szep. 6. (K), 17.40
Nálunk is előfordult párszor utóbbi időben, hogy eltünedezett a $_SESSION, és az derült ki, hogy annyira elfogyott a memória, hogy a php nem tudta elmenteni a tartalmát fájlba. Talán érdemes nálatok is ezt leellenőrizni a memory_get_usage() függvénnyel, valamint ezzel a script végén:

try {
  session_write_close();
}
catch (Exception $e) {
  print_r($e);
}

Egyszerre annyi AJAX kérés mehet egyébként, amennyit a szerver bír, de az adott munkamenetben a php script rendelkezésre álló memóriájába mindennek be kell férnie, ami alapesetben nyolc mega.
7

Szebernél a pont

gtoma · 2011. Szep. 6. (K), 18.08
Beraktam egy késleltetést az ajax hívásba, hogy egyszerre csak egyet indítson. Ment mint a karikacsapás. Sajnos ez nem jó, mert a jelenlegi kialakításban nem lehet tudni, hogy hány esetben indulna Ajax lekérés, és ez igen idióta lenne már 10 hívás esetén is. Úgyhogy lehet újraírni a kódot, de legalább most már tudom mi a pálya.


Nagyon köszönöm mindenkinek a segítségét, új területen tisztult a kép!
10

Tüneti kezelés

janoszen · 2011. Szep. 6. (K), 19.43
Tüneti kezelés, két konkurens AJAX hívás esetén hasonló módon fölül fogják egymást írni. Inkább tegyél lockolást a session kezelődbe.
12

Lockolást beépítem.

gtoma · 2011. Szep. 7. (Sze), 13.25
Oké! akkor megfogadom a tanácsotokat, és beépítek egy lockolást.

Sajnos azt a kódrészletet, aminél kiborult a bili, akkor is át kell írnom, mert meghatározhatatlan volt, hogy hány db ajax lekérés indul.

Köszönöm szépen, nagyon jól érzem magam, hogy kicsit tisztult ebben a kép. Persze tudtam, hogy a phpnek van futási ideje, de valahogy nem számoltam, hogy ilyen gondokat okozhat.

Ez a felmerült instabilitás teljesen "felzaklatott" mindig :)

Köszönöm Nektek!