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:

$_SESSION['labda'] = 52;

print "
<script>
ajaxlekeres();
</script>
"
Ez mondjuk a JS:

function ajaxlekeres() {
    var BaseURL = 'server.php';
    var myPars      = 'com='+comok+'&rnd='+this.RND;
    var myAjax = new Ajax.Request( BaseURL, {
                parameters: myPars,
                onComplete: FrissitesUpdate
    });
}
function FrissitesUpdate(originalRequest) {
    $('target').innerHTML = originalRequest.responseText;
}
server.php:

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:

session_module_name("user");

function session_open($path, $name) {
   return(true);
}

function session_close() {
   return(true);
}

function session_read($id) {
    global $DB_HOSTNAME, $DB_FELHNEV, $DB_PASSWORD;
    $DB_CONNECT = ConnectDatabase();
    $sql = "select * from session where id='" . $id . "'";
    $result = mysql_query($sql, $DB_CONNECT);
    $row = mysql_fetch_assoc($result);
    mysql_close($DB_CONNECT);
    return($row["data"]);
}

function session_write($id, $data) {
    global $DB_HOSTNAME, $DB_FELHNEV, $DB_PASSWORD;
    $DB_CONNECT = ConnectDatabase();
    $sql = "update session set data = '" . addslashes($data) . "' , user='', time='".date("Y-m-d H:i:s")."' where id='" . $id . "'";
    mysql_query($sql, $DB_CONNECT);
    if(mysql_affected_rows()) {
        mysql_close($DB_CONNECT);
        return(true);
    }
    $sql = "insert session set data = '" . addslashes($data) . "', id='" . $id . "'";
    mysql_query($sql, $DB_CONNECT);
    mysql_close($DB_CONNECT);
    return(true);
}

function session_remove($id) {
    global $DB_HOSTNAME, $DB_FELHNEV, $DB_PASSWORD;
    $DB_CONNECT = ConnectDatabase();
    $sql = "delete session where id='" . $id . "'";
    mysql_query($sql, $DB_CONNECT);
    mysql_close($DB_CONNECT);
    return(true);
}

function session_gc() {
    global $DB_HOSTNAME, $DB_FELHNEV, $DB_PASSWORD;
    $DB_CONNECT = ConnectDatabase();
    $life = (24*60*60);
    $sql = "delete from session where time < '" . date("Y-m-d H:i:s", time() - $life) . "'";
    mysql_query($sql, $DB_CONNECT);
    mysql_close($DB_CONNECT);
    return(true);
}

session_set_save_handler("session_open", "session_close",
   "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!