2008. január 14., hétfő

PHP Session session.gc.maxlifetime helyes beállítása

Az alap probléma, amivel sok helyen találkozhatunk, nagyon sokan nem tudnak vele mit kezdeni az az, hogy szeretnénk, ha a felhasználóinknak akár egy órát is beállíthatnánk "inaktivitási időnek". Azaz, ha nincs aktivitás az oldalon, akkor ennek az időnek a lejártával, szűnjön meg a munkamenet, ergo a usernek újra be kelljen lépnie.

(Ez ugye inkább a fordított irányban szokott problémát okozni, vagyis az adminok panaszkodnak, hogy elmennek kávézni, cigizni és flörtölni a büfés csajjal, mire visszaérnek és befejezik a cikk megírását, és megnyomják a mentés gombot, kilépteti őket a rendszer, így elvesznek az addig beírt okosságok.)

Ekkor szokták a címben is megjelölt session.gc.maxlifetime direktívát álíltgatni htaccess segítségével, vagy az ini_set mágikus függvény bevetésével.
Ez rendben is van, ezt így kell használni, így helyes. De akkor miért van az, hogy mégis rengeteg fórumon dobják fel a témát, miszerint egyszerűen nem tudják pl. 24 percnél tovább "bent tartani" a felhasználót a rendszerben?

Meglepően kevesen tudják (vagy jut eszükbe), hogy a session fájlok a fájlrendszeren egy közös könyvtárban helyezkednek el (Linux esetén alapértelmezetten a /tmp könyvtárban). Ezek a fájlok semmilyen módon nincsenek megkülönböztetve, hogy melyik domain-hez tartoznak. Az elnevezésük ugyan azon a formán alapul: sess_78n43ifz23o83znf8o2zn4g2


Mikor a garbage collector benéz a session fájlokat tároló könyvtárba, megnézi a php.ini-ben beállított maxlifetime értéket, ami mondjuk 24 perc, és azt csinálja, hogy a 24 percnél régebbi session fájlokat törli. Mint azt az előző bekezdésben jeleztem volt, nem tesz különbséget domain-ek között, és ha akarna sem tudna, ebből az következik, hogy mi hiába állítjuk be a gc.maxlifetime-ot 30 percre, ha az általunk generált session fájl régebbi mint 24 perc, és a cron éppen törlést végez, habozás nélkül törli a mi fájlunkat is.

Akkor mi lehet a megoldás?
Beállíthatunk magunknak egy saját session.save_path értéket, vagy írunk egy saját session kezelőt a session_set_save_handler segítségével.

session.save_path:
Legegyszerűbb megoldás, ha a session fájlok tárolására alapértelmezetten beállított könyvtáron belül egy saját könyvtárba pakoljuk a mi munkamenet fájljainkat. Hogy platform független legyen a kódunk, először ki kell találnunk, hogy a file separator / vagy \.
Ezután ellenőrizzük, hogy az általunk használni kívánt könyvtár létezik-e, ha nem, akkor létre hozzuk, majd beállítjuk az új save_path-ot.:

Mostmár a mi session fájljaink "védettek" az alapértelmezett garbage collector-tól.
Amire azonban nagyon figyeljünk: Ha a session.save_path  mélysége több mint kettő, az automatikus szemét takarítás nem fog működni!

A session_set_save_handler lehetőségről nem írok bővebben, mivel ezernyi módon lehet megvalósítani. Nekem leginkább a MySQL alapú handlerek szimpatikusak, viszont azt még mai napig nem tudom, hogy egy komolyabb terheltségű oldalon ez mennyire tud belassulni, illetve szét floodolni a mysqld-t. Egy biztos, ebben az esetben meg tudjuk szabni, hogy a garbage collector hogyan működjön (sőt muszáj), és ez nem egy utolsó szempont :)

Ennyi.

4 megjegyzés:

  1. A DIRECTORY_SEPARATOR az amit te valojaban keresel.

    VálaszTörlés
    Válaszok
    1. Akár. Köszi az észrevételt :)

      Törlés
    2. Egyebkent nem ertem ezt a melysegi kerdest. Automata szemet eltakaritas tudomasom szerint elsosorban Debian/Ubuntu rendszereken van, egy cron job rendszeresen felnyalja a /var/lib/php5 mappat, es torli a php.ini -ben (es csak ott) definialt lifetime alapjan a session fajlokat. Ezen felul masutt nem keres, tehat ha mondjuk a /var/www/ensitem.com/session ala rakod be ezeket a cuccokat, akkor a szemettakaritas _sosem_ fog elsulni rajtuk, akarmilyen melysegu a path.

      Ami a normal session.save_path alatti torteneteket illeti, Debian/Ubuntu alatt nincs -maxpath parameterezese a scriptnek, szoval a 15 szint melysegu pathen is tortenik szemetgyujtes.

      Van par mas disztro, ahol szinten van szemettakarito script, de ez disztronkent kulonbozo lehet (meg akar az is, hogy figyelembe veszi-e a php.ini ertekeit, es ha igen, mennyire). Ezzel csak arra szeretnem felhivni a figyelmedet, hogy ezeket a dolgokat ne kezeld axiomakent, mert sokkal keplekenyebbek annal. Nem "igy mukodik" hanem "nalunk igy mukodik".

      A helyes megoldasa a gc idejenek a novelesenek az, ha irunk egy levelet az adminisztratoroknak, hogy szeretnenk, ha ez ennyi-annyi perc lenne, es kulon felhivnank a figyelmet, hogy nem szeretnenk a tul koran kelo szemeteskocsival hadakozni.

      Törlés
    3. Az az igazság, hogy pár évvel ezelőtt még örömmel elvitáztam volna veled (az utolsó gondolatoddal főleg ;)), de mivel már 4 éve szerencsére bottal sem piszkálok PHP-t (2008 januári a bejegyzés), így mostmár nem tudok olyan elkötelezetten harcba szállni az érveimmel, mert már nem is nagyon vannak a témában :D

      Egy biztos, ez egy jól bevált, sok helyen működő módszer volt annakidején :)
      Azóta sokminden változott, akár lehet teljesen elavult is a gondolatmenet, pusztán érzelmi okok miatt maradt benne az importban ideköltözésem alkalmával :)

      Törlés