ugrás a tartalomhoz

Többlépcsős folyamat leprogramozása PHP-ban

killroy · 2009. Már. 29. (V), 15.34
Sziasztok!

A többlépcsős folyamat alatt egy olyan oldalt értek, mint pl amikor megrendelsz egy webáruházban egy terméket. A következő lépéshez szükséges az előző lépés teljesítése. Az ilyen folyamatokhoz, legyen az bármi, még egy ábrát is mellékelnek, hogy éppen melyik szinten vagy miközben megmutatják hogy milyen szinteken vagy túl és milyen szintek állnak még mögötted.

Lehet hogy én bonyolítom túl a dolog, nekem egy termék kosárba helyezéséhez kellene egy ilyen több lépcsős folyamat. A termék tulajdonságait kell beállítani az egyes szinteken és ha mindent beállított a felhasználó akkor bekerül a kosárra.

Úgy gondolom, hogy biztos van az ilyen jellegű problémák megoldására egy bevált módszer és ezt szeretném megkérdezni hogy mitévő legyen ilyen helyzetben. Engem tulajdonképpen az elv érdekelne, vagy ha valaki ismer egy jó leírást az interneten azt is megköszönném.

Előre is köszönöm!
 
1

Munkamenetkezelés

thgab · 2009. Már. 29. (V), 16.47
Ez a kulcsszó!:)
Ha helyesen tölti ki a tulajdonság formot akkor ezt valamilyen változó segítségével beállítod a SESSION-ben, és csak akkor engeded tovább ha ez megvan, egyébként nem. Minden lépésnél az aktuális lépéshez tartozó scriptben ellenőrzöd hogy az előző lépéseknél rendben volt-e minden.
2

temp tábla

deejayy · 2009. Már. 30. (H), 07.21
Hozz létre egy temporáris táblát, amiben tárolod a folyamat egyes elemeit. Ha az utolsó lépést is lenyugtázza a felhasználó, akkor pedig élesítsd az adatokat.
3

re: temp tabla

Greg · 2009. Már. 30. (H), 13.21
ezt ugye nem gondoltad komolyan?
4

Nem csináltam

deejayy · 2009. Ápr. 7. (K), 08.41
Még nem csináltam ilyet, de érdekelne, mit látok rosszul?
9

Én sem

inf · 2009. Ápr. 15. (Sze), 02.04
Na vajon...
A temp tábla csak egy adott db connection érheti el. A phpben nem tudod ezt a connectiont továbbadni, tehát el fog veszni a táblával együtt.
Nyilván a sessionben kell tárolni az egyes tulajdonságokat, meg hogy éppen hányadik lépésnél tart a júzer, mert két kérés között az az egyetlen tárolási forma.

Hmm egyébként elgondolkodtam azon, hogy a sessionjeimet memcache-ben tároljam adatbázis helyett, bár onnan elég nehézkes a listázás.
5

DOS

janoszen · 2009. Ápr. 7. (K), 09.25
A tábla létrehozása elég költséges művelet plusz hány táblád lesz így? Elég könnyen be lehetne borítani a szervert. ;) A munkamenet azért jobb, mert ugyanúgy el tudsz benne tárolni mindent, viszont automatikusan takarítódik és nem cseszteti az adatbázist.

Az adatbázis a barátod, de csak ha jól használod. Hetente takarítok olyan felhasználók után, akik indexek nélkül tartják a tábláikat és mindenféle temptábla-varázslásokat követnek el. Ilyenkor aztán repül a letiltás. :)
6

Félreértesz

deejayy · 2009. Ápr. 13. (H), 16.46
A temp-tábla létrehozáskor én arra gondoltam, hogy egyszer létrehozza, aztán dolgozik vele. Lehet játszani az elévüléssel meg ilyenekkel, kis ráfordítással pl.

A másik pedig, hogy elképzelhető a php session paramétereinek tárolása adatbázisban is. Ez mondjuk csomó kézi dolgot automatizál. Döntés kérdése, hogy sessionben vagy db-ben tárolja, csak felvetettem, ha plusz egy megoldási mód kellene.
7

Ok

janoszen · 2009. Ápr. 13. (H), 19.18
Ez mondjuk egy fokkal jobb, de nem értem, mit nyersz vele a sessionhöz képest, ahol gyakorlatilag a PHP objektumot tudod eltárolni, nem kell oda-vissza konvertálni és szivatni az adatbázist. (Nagy terhelés mellett az, hogy minden műveletet adatbázisban csinálsz, garantáltan beborít egy pár dolgot.)

Azt a mondatodat sajnos nem értem, hogy a session DB-ben tárolása mit automatizál a filehoz képest, magyarázd el légyszi.
8

időeltolódás a lépések között

erenon · 2009. Ápr. 14. (K), 10.21
Akkor látnám értelmét, ha a különböző lépések között hosszú idő eltelhet, ameddig lejár a session. Például berakja a kosárba, majd holnap megmutatja A-nak meg B-nek, majd alszik rá egyet, és aztán megvásárolja. Bár itt igazából elég nehezen elválasztható, hogy mi is igazából a "több lépcsős folyamat", mert ez szerintem már különálló akciók halmaza. (kosárba rak, megvásárol)
12

Ez igaz

janoszen · 2009. Ápr. 15. (Sze), 08.05
Ez mondjuk az egyetlen előny. Ha ilyen funkciót akarsz biztosítani, akkor valóban jobb az adatbázis, azonban nem biztos, hogy üzemköltség szintjén reális. Cachelni mindenképp kell(ene).
11

Pont, hogy nagy terhelésre jó

inf · 2009. Ápr. 15. (Sze), 02.11
A fájlrendszer 10000 fájl felett kiakad (legalábbis én azt olvastam), az adatbázis meg lazán elvan 10k rekorddal. Szerintem nagyon rossz oldalról közelíted meg a dolgokat. Nagy terhelésű oldalaknál garantált, hogy nem fájlokban tárolják a munkameneteket.
13

Hol olvastad?

janoszen · 2009. Ápr. 15. (Sze), 08.14
Nem tudom, ezt hol olvastad, de nem lett volna baj egy kicsit jobban utánajárni. A filerendszer akkor érzi rosszul magát, ha egy könyvtárban van sok file. De ez nem is követelmény, hiszen lerakhatod így is: sessions/a/a5/a5b6...

Egyébiránt nem kötelező a filerendszer sem (vagy írtam volna ilyet?) tarthatod memcacheben is pl. Egy napi 35k látogatójú portál session adatai elférnek 100 megában.

Ezzel szemben 10k bejegyzéssel a MySQL valóban jól elvan, viszont kénytelen vagy minden oldalletöltéskor írni bele hogy ne évüljön el a session, na az viszont már kicsit jobban fáj.
15

Hát

inf · 2009. Ápr. 17. (P), 00.36
Hát ebbe még nem gondoltam ennyire bele. Eddig mindenhonnan azt hallottam, hogyha nagy adatmennyiséggel akar dolgozni az ember, akkor adatbázisból szedje, és hanyagolja a fájlokat. Egyébként igen, én is arra gondoltam, hogy ha 10k fájl van egy mappában, akkor van gond, szétosztva nyilván nem para.
Az adatbázisnak viszont az az előnye, hogy aktív sessionnel rendelkező emberkék jogait realtime módosíthatod az admin felületről, plusz csinálhatsz egy szép rendezett listát az aktív userekről. Kérdés, hogy megéri e :-)
Ezzel szemben 10k bejegyzéssel a MySQL valóban jól elvan, viszont kénytelen vagy minden oldalletöltéskor írni bele hogy ne évüljön el a session, na az viszont már kicsit jobban fáj.

Ha a db terheltségére gondolsz, akkor ebből a szempontból valóban fájdalmas lehet.
30

DB vs file

Hodicska Gergely · 2009. Ápr. 19. (V), 00.02
Eddig mindenhonnan azt hallottam, hogyha nagy adatmennyiséggel akar dolgozni az ember, akkor adatbázisból szedje, és hanyagolja a fájlokat.
Ehhez két apróság, a DB is fájlokban tárolja az adatokat. ;) Vagy pl. lásd ezt a tesztet (volt már többször itt linkelve).
10

Session adatbázisban

inf · 2009. Ápr. 15. (Sze), 02.07
Én személyszerint a session adatbázisban tárolásának a híve vagyok, mert sokkal egyszerűbb a módosítás, és a listázás is.

Ha mondjuk admin oldalról meg akarom keresni egy adott user sessionjét, akkor csak egy select kell a sessions táblára, és nem kell a fájlok között keresgélnem.
14

Persze

janoszen · 2009. Ápr. 15. (Sze), 08.21
Namost tegyünk egy apró különbséget. Az, hogy Te tudni akarod, hogy a user hol van bejelentkezve és az, hogy a sessionadatok hol vannak, egyáltalán nem feltétlenül kell ugyanott legyen. Az előbbi ingormáció sessionönként egyszer frissíted, az utóbbit oldallekérésenként. Persze ha spórolni akarsz az energiáddal, hajrá, csak nehogy egy backup művelet belockolja az adatbázisodat és meg se tudjál mozdulni. (Örököltem egy rendszert ilyen jellemvonásokkal. Mysqldump = 5 perc leállás.)
16

Tetszik

inf · 2009. Ápr. 17. (P), 05.49
Tetszik ez a megközelítés. Tényleg értelmesebb különválasztani a kettőt. Azt hiszem még van min agyalnom :D

szerk:
Közben ki is gondoltam, hogy a táblába a sessionid meg az userid kerül majd, meg egy módosítási dátum, amit a garbage figyel, és 10 percenként frissít a memcacheből.
A memcacheben a sessionid lesz az azonosító, és elég sok dolog bele fog kerülni.

A szemétgyűjtés persze megoldható tábla nélkül is, a táblának igazából az a funkciója, hogyha csinálok admin oldalról egy lekérést, akkor össze lehessen párosítani az useridket a sessionidkkel, és ha létezik a módosított userhez session, akkor a memcache kapjon egy értesítést arról, hogy frissítenie kell valamilyen adatot.

Arra gondoltam, hogyha valaki elkezd írni egy cikket, akkor a piszkozatot a memcache-be mentem néhány percenként, aztán ha elkészültek kerülnek be a megfelelő táblába. A garbage meg törlés előtt megnézi, hogy van e ilyen piszkozat a sessionnél, és ha van, akkor menti a piszkozatos táblába, hogy később lehessen folytatni. Ez pl sztem tökjó, ha valaki ottfelejti az írását a gépnél, vagy hosszú cikket ír, és sokáig nem aktív.
(Az automata mentést meg megcsinálom úgy, hogy csak akkor fusson le, ha gépelt is valamit az illető.)

Szóval tetszik az ötlet, bár még nem értek a memcache-hez, de gondolom több időt fogok a telepítéssel tölteni, mint ami alatt megtanulom. :-)
17

Memcache

janoszen · 2009. Ápr. 17. (P), 10.05
Én így csinálnám: A session adatokat memcachebe tenném meghatározott lejárattal. Bejelentkezéskor a user nevét és session idját betenném adatbázisba. Időnként futtatnék egy takarító scriptet, ami ugyanezen táblából a "mikor láttuk" mezőből kiválasztja a session lejáratnál régebbi bejegyzéseket és végignézi, hogy létezik-e még a session és ha nem, kiüti, majd az egész művelet végén megfrissíti a nézett bejegyzések "mikor láttuk" mezőjét.. Ha akarod, ezt az "indexet" memory táblában is tarthatod és akkot jó gyors is lesz. Persze az egész csak egy ötlet, nem próbáltam ki.

Másik ötlet: vegyél föl reverse rekordokat a memcachebe.
PL 'user_joskapista' => array('a5fdsadar3ada').
Még talán listázni is tudod a memcache kulcsokat getExtendedStats()-al.

Ami a memcachet illeti, minden normális Linuxon van csomagban, Windowson meg nem szeretnél PHPt üzemeltetni.
18

Ehm

inf · 2009. Ápr. 17. (P), 17.09
Persze, hogy üzemeltetni nem szeretnék Windowson, viszont a fejlesztést azon csinálom localhoston. Egyszerűbb, mint a feltöltéssel szórakozni, meg könnyebben lehet backupokat csinálni. (Persze biztos van program, amivel lehet online szerkeszteni, de nem ismerek ilyet.)

Egyébként kb úgy csinálnád, mint én.
Vannak olyan dolgok ezek szerint, amiket érdemes a sessionbe gyűjteni, és csak a session lejártakor hozzáadni az adatbázishoz. Így nem lassítják a lekérdezést.

Pl. history-nél ha loggolni akarok minden aktivitást, akkor memcacheben gyűjtöm, és a végén adom a dbhez, így nem lassítom a lekéréseket azzal, hogy minden alkalommal db-t frissítek.
19

Online szerkesztés

Poetro · 2009. Ápr. 17. (P), 17.35
Mivel több mint két és fél éve online szerkesztem a fájlokat, elmondhatom, hogy léteznek ilyen programok. Van amelyik kényelmesebb, van amelyik kevésbé. Lehet FTP-vel, SCP-vel, vagy SFTP-vel szerkeszteni fájlokat online. Ha a szerver és a szerkesztőd között van közös protokoll, akkor nem probléma, egyébként meg WinSCP. Legtöbb szerkesztő tud FTP-t vagy akár FTPS-t. Lásd a fejlesztői környezetekről szóló blogbejegyzésem.
21

Vim

Ustak · 2009. Ápr. 17. (P), 17.46
kimaradt :-)
23

Kösz

inf · 2009. Ápr. 17. (P), 18.16
Kösz, tetszett a bejegyzés.

Én mondjuk NetBeans-el foglalkoznék szívesen, mert az java-nál elég elterjedt, így elég csak egy helyen megtanulni a kezelését, másrészt NetBeans sok másik nyelvhez is van, nagyon nagy project, így biztos, hogy nem áll le a fejlesztés php terén sem, sőt valszeg gyorsabb lesz, mint az összes többinél.

Ezek szerint az egyedüli, ami igazán kiforrott php szerkesztők terén az a Komodo. Még agyalok rajta, hogy ilyenbe belefogjak, mert azért nekem már megvan az ugyan elavult, de biztonságos módszerem :D Leginkább az érdekel, hogyha bármi kánya van a szerverrel, akkor az itthoni gépemen legyen egy biztonsági mentés arról, amivel eddig dolgoztam. Ha ilyen tükrözést is be lehet lőni rajta, akkor szívesen megnézem, amúgy nem érdekel annyira.

Egyébként kicsit elkanyarodtunk az eredeti témától, de ez kifejezetten tetszik. :-) Legalább nem olyan sablonos a fórum felosztása, mint prog.hu-n.
20

Fejlesztés

janoszen · 2009. Ápr. 17. (P), 17.36
Hát mindenki úgy szivatja magát ahogy jól esik, de a Windowsos és a Linuxos Apache működés között vannak különbségek. Linux alatt pl sokkal könnyebb hibát keresni ha véletlenül mondjuk egy PHP bugra futsz rá. Azokból pedig van elég. Én azt szoktam mondani, hogy azon a rendszeren kell fejleszteni (verzióra pontosan) amin futni fog, különben majd meglepődsz. :)

A loggolásra meg ott a syslog, kár erölködni vele. DB-ben nem érdemes loggolni, főleg nem realtime. User interakciókat talán, bár kétséges hogy kell-e.
22

Ez azért nem ilyen egyszerű

inf · 2009. Ápr. 17. (P), 17.57
Szerintem nem ilyen egyszerű a kérdés. Egyelőre van egy godaddys host, amin a coming soon, meg ilyesmik mennek, szóval nem kell sokmindent intéznie, viszont az oldal nem biztos, hogy ezen fog futni, mert szerintem nem fogja elbírni, ha hirtelen egyszerre 5-10k látogató felugrik rá a nyitáskor. Szóval egyelőre még nincs meg a szerver, amin futni fog, másrészt meg fogalmam sincs, hogy a godaddy milyen lehetőséget ad a hostjához, majd egyszer átnézem, ha olyanom lesz, de elképzelhető, hogy nem fogom tudni csak úgy beállítani, hogy pl curl legyen, stb.

Szal egyelőre nekem ez így kényelmesebb, mint az online szerkesztés. Majd ha eljutottam abba a fázisba, hogy már lehet tesztelni, akkor felteszem a szerverre és ráengedek párszáz ismerőst tesztelőnek, szóval majd akkor foglalkozom a dologgal, amikor itt az ideje.

szerk:
Ok, nem szóltam :-)
Egyrészt lehet online szerkeszteni godaddynél, másrészt lehet írni a php.ini-be. Meg úgy összességében nagyon komoly az oldal. (Az egyedüli, amit hiányolok belőle, az a notepad++, nincs kódszínezés, ha tab-ot nyomok, akkor focust vált, etc.)
24

Off: Ójaj...

janoszen · 2009. Ápr. 17. (P), 21.41
Nem irigyellek.
25

:-)

inf · 2009. Ápr. 18. (Szo), 05.54
Kibírom :D
Egyelőre csak tanulgatom, hogy kell komolyabb oldalakat csinálni. Ha nem így lenne, akkor fix, hogy nem a php-t választom, hanem jsp-t vagy asp.net-et. Ha befut az aktuális oldal, akkor előbb-utóbb újraírom komolyabb nyelven is, mert sokkal gyorsabb, ha nem kell minden lekérésnél újraépíteni az objecteket.

Egyébként ha valaki adatbázisból vagy memcachedből akar sessiont kezelni, akkor előbb nézze meg ezt a linket, mert ezzel kapcsolatban van egy elég idegesítő bug a php-ben, amit évek óta nem javítottak.
26

Jajj...

janoszen · 2009. Ápr. 18. (Szo), 09.24
Ki mondta, hogy a PHP belső session kezelőjét kell használni? Szerintem idegesítő, debuggolhatatlan és szar. Sokkal egyszerűbb írni egy osztályt, ami ellátja ugyanezeket a feladatokat, az adatokat maga kezeli a sessiont, nem a PHP-s $_SESSION változón keresztül. Ja és még működni is fog, az előzővel ellentétben.

Ja egyébként ez nem bug, ez design döntés. session_write_close meghívása destruktorban a barátod.
27

Ohh..

inf · 2009. Ápr. 18. (Szo), 09.40
Hát én úgy voltam vele, hogy a $_SESSION-ön keresztül csinálom, mert az egy egységes felület, akkor is megy, ha nem írok hozzá külön kódot. Azt, ami nekem kell megcsinálja, szóval nincs vele gondom.

Destruktor helyett inkább ezt használom:

register_shutdown_function('session_write_close');
egyszerűbb.

Még a session_id generáltatást kell átírnom benne, a szemetet meg rohadtul nem ő fogja kezelni. Szóval alakul a session kezelésem. Azt hiszem jót tett, hogy pár hónapot oop meg refactoring olvasgatással töltöttem, mert most elég könnyen megy a fejlesztés. Csak azt kell átgondolni, hogy milyen feladat melyik kategóriába menjen (mvc), a többi meg már jön magától.
32

+1 kis kiegésztéssel

Hodicska Gergely · 2009. Ápr. 19. (V), 00.30
1. register_shutdown_function('session_write_close');
Szerintem is ez egy jó stratégia (ha jól rémlik, akkor pl. drupal is ezt használja). Egy apró kiegészítést azért tennék (ha már ilyen kötekedős napom van :P): érdemes lehet előbb, expilict módon meghívni a session_write_close-t akkor, amikor már az érdemi feldolgozás véget ért, és már csak a kimenet generálása van hátra. Ennek oka az, hogy előfordulhat, hogy már elkezdünk kitolni egy olyan kimenetet, ami maga is dinamikus kiszolgálást kezdeményez (pl. ajax, vagy pl. PHP-ból kiszolgált statikus tartalom) még azelőtt, hogy a kimenet teljesen ki lett volna szolgálva (nagy oldal vagy pl. lassú kliens). Mindez azt eredményezheti, hogy ez a kérés már akkor próbálja meg kiolvasni a sessiont, amikor az eredeti kérés még nem zárta azt be. Ez főleg saját session kezelő használata esetén tud gondokat okozni akkor, ha nincs megoldva a kölcsönös kizárás a session adatok elérésekor (pl. a második kérés is még az eredeti kérés által olvasott állapotot kapja meg, amit mondjuk változtatás nélkül visszaír, ezáltal felülvágja az eredeti kérés módosításait).
34

+1

janoszen · 2009. Ápr. 19. (V), 01.33
Arra is rohadtul illik figyelni, hogy a favicon.ico meg a haverjai ne fussanak rá az alkalmazásra ha szeretnél még hajat a projekt vége után. Ha azt látod, hogy kétszer kapja meg a PHP a vezérlést, akkor az tuti hiányzó kép, favicon.ico vagy valami hasonló gonosz lekérdezés.
29

miért?

Hodicska Gergely · 2009. Ápr. 18. (Szo), 23.42
Szerintem idegesítő, debuggolhatatlan és szar.
Miért gondolod ezt?

Sokkal egyszerűbb írni egy osztályt, ami ellátja ugyanezeket a feladatokat, az adatokat maga kezeli a sessiont,
Pl. egy lokális memdisken tároló cuccot, ami kapásból halott, ha több szerveren kéne használva legyen? ;)

Mellesleg megjegyezném, hogy a lesajnált PHP saját session kezelője pl. figyel a kölcösnös kizárásra (pl. ajax kérések esetén érdekes lehet), amire egy saját cucc jóformán sohasem szokott.

session_write_close meghívása destruktorban a barátod
Ezzel azt mondod, hogy a destruktor hívja meg saját magát. ;) Inkább a kiszolgálás végekor kell meghívni a session_write_close-t.
33

Nem voltam pontos

janoszen · 2009. Ápr. 19. (V), 01.16
Nem voltam elég pontos. Ami a PHP saját session handlerét illeti, nem egyszer szívtam pl az említett probléma kapcsán is, hogy adatbázisba ment volna az információ, azonban az adatbázis-kapcsolat már nem létezett. Ennek hatására a megfelelő modul nekiállt példányosítani egyet. Mi sem kellett több, az az Apache szál akkorát segfaultolt mint a ház. Windowsokon komplett beállt, Linux alatt meg belehalt a forkolásba. Amikor próbáltuk debuggolni, csak azt láttuk, hogy a működési logikának megfelelően megjelentünk a session handlernek átadott függvényekben, de olyan folyamat hogy láttuk volna, mitől hívja meg, nem volt.

Ami a saját session handlert illeti, lehet abból jót írni, nem feltétlenül ramdiskre, de pl a memcache most már tud redundanciát, stb. szóval ha nagyon akarod, lehet abból jót csinálni. Persze érteni kell hozzá, de ez meg nem újdonság. Azt meg, hogy hogy figyel a PHP saját session handlere egy random filerendszeren (NFS? GFS?) azért úgy megnézném közelebbről. Az mindenhonnan elérhető sessionök pedig ugye a clusterezhetőség alapvető követelményei.

Amit a destruktorral gondoltam, hogy a session osztály vagy a rendszer destruktorában (kialakítástól függően) hívjuk meg a session_write_close-t. A lényeg, hogy ott kell keresni a megoldást.
37

...

Hodicska Gergely · 2009. Ápr. 19. (V), 02.26
Ami a saját session handlert illeti, lehet abból jót írni, nem feltétlenül ramdiskre
A példa csak abból jött, hogy nem is olyan régen ilyet csináltatok winstonnal, ami ugye nem túl skálázható megoldás. ;)

Amit a destruktorral gondoltam, hogy a session osztály vagy a rendszer destruktorában (kialakítástól függően) hívjuk meg a session_write_close-t. A lényeg, hogy ott kell keresni a megoldást.
A probléma abból fakad, hogy 5.0.5 óta a destruktorok előbb hívódnak meg, mint a session lezárása. Kicsit fura, hogy a destruktorból hívd meg az amúgy bregisztrált close handlert, de végül is működni fog.
41

Valóban

janoszen · 2009. Ápr. 19. (V), 12.57
A példa csak abból jött, hogy nem is olyan régen ilyet csináltatok winstonnal, ami ugye nem túl skálázható megoldás. ;)


Valóban, de a történelem beigazolta, hogy nem is volt szükség rá. Egyébként az egész session handler mágikus módon volt vagy 200 sor szóval semeddig nem tartott volna kicserélni, főleg hogy minden osztály a megfelelő API-n keresztül birizgálta.

A probléma abból fakad, hogy 5.0.5 óta a destruktorok előbb hívódnak meg, mint a session lezárása. Kicsit fura, hogy a destruktorból hívd meg az amúgy bregisztrált close handlert, de végül is működni fog.


Pont ilyen megfontolásból zártam le destruktorból a sessiont. Úgy 2 éve, amikor még a PHP sajátját használtam.
28

PHP bug

Hodicska Gergely · 2009. Ápr. 18. (Szo), 23.34
Linux alatt pl sokkal könnyebb hibát keresni ha véletlenül mondjuk egy PHP bugra futsz rá.
Eddig hány hibát találtál te magad, és ebből hny olyan volt, ahol a linux segített debuggolni?
35

strace

janoszen · 2009. Ápr. 19. (V), 01.35
Szoktam a PHP kódját nézegetni és a strace is sokat segít. A sessionös-segfaultolós problémát pl így debuggoltam ki, de a subversiont is volt már szerencsém. A PHP-val kapcsolatban pont a téma problémája kapcsán volt az, hogy Windows alatt teljesen beállt az Apache (futott, nem válaszolt, nem szolgált ki, nyitva tartotta a listen socketet), Linux alatt pedig csak az adatott szál repült. Nyilván az MPM-beli különbségek voltak, de ez elég probléma lehet egy PHP bug kergetése közben.

Egyébként ha az ember nem is óhajt ilyesmibe belemenni, Windows alatt egy normális tail nincs (tudtommal), amivel rendesen lehetne realtime nézni a logot. Plusz a feldolgozáshoz kapcsolódó egyéb feladatokat sokkal nagyobb probléma tesztelni. Hogy mondjak egy példát, egy fejlesztőcsapatban kialakítasz egy struktúrát a cronjobok nyilvántartására, amit be is küldesz SVN-be. Ebből Linux alatt gyerekjáték a megfelelő crontabot előállítani, Windows alatt viszont szerintem egy vagon MSDN olvasás és guglizás befigyel. :)

Azt meg már csak úgy csendben jegyzem meg, hogy célszerű lenne az éles környezethez minél hasonlóbb környezetben fejleszteni, mert aztán jönnek a meglepetések. A PHP verziókülönbségek ilyen szempontból halálosak, de én a platformon is gondolkoznék.
38

akkor nem olyan gyakori

Hodicska Gergely · 2009. Ápr. 19. (V), 02.29
Ezek ok, csak úgy fogalmaztál, hogy PHP esetén nem ritka, míg szerintem piszok ritka, hogy bugba fusson bele az ember (amit említesz az is alapvetően user error), de semmikép nem mindennapos.
31

Memcache LRU, slab classes

Hodicska Gergely · 2009. Ápr. 19. (V), 00.22
Közben ki is gondoltam, hogy a táblába a sessionid meg az userid kerül majd, meg egy módosítási dátum, amit a garbage figyel, és 10 percenként frissít a memcacheből.
A memcacheben a sessionid lesz az azonosító, és elég sok dolog bele fog kerülni.
Van két dolog, amit mindketten kihagytok a számításból. Egyrészt a memcache nem garantál semmit azzal kacsolatban hogy amit egy adott időre beleírsz, az benne is marad addig az ideig. Csak annyit garantál, hogy a lejárati időnél később nem ad vissza egy adatot. Ezért sessiont tárolni benne csak megfontoltan lehet. Méretezni kell a memcache számára adott memória méretet annak érdekében, hogy ne telhessen meg, különben a legrégebben nem használt elemeket a memcache kivágja szó nélkül. Szitén érdemes arra figyelni, hogy rendundáns legyen, érdemes legalább két memcache-be is menteni az adatokat. Ez már csak azért is érdekes lehet, mert bármikor elromolhat egy gép, vagy éppen újra kell indítani, viszont session esetén tipikusan nem megengedhető, hogy csak úgy elvesszen.

És van még egy kevésbé ismert dolog: a memcache a számára adott memóriát fix méretű cellákákból álló lapokra osztja. Egy lapon belül a cella méret fix. Amikor leraksz valamit memcachebe, akkor megkeresi azt a lapot, aminek a cella mérete már nagyobb, mint a lerakni kívánt adat, és van még rajta üres hely. Ha nagyon össze-vissza méretű dolgokat tárolsz le memcache-be, akkor előfordulhat könnyen olyan eset is, hogy a különböző méretű lapok létrejöttével "betellik" a memcache számára adott memória, ezen lapok telítettsége viszonylag alacsony lesz, de ennek ellenére ha jön egy még nagyobb méretű adat, akkor már nem fogja tudni letárolni. Ez cache jellegű használat esetén is elég fájó, hiszen az adatok előállítását végző "drága" művelet le fog futni mindig, session jellegű felhasználás esetén meg végképp szívás. Ha számoli kell ilyesmivel, akkor érdemes a memcache indításakor a lehetséges legnagyobb méretű objektumot automatikusan letráolni.
36

Paraméterezés

janoszen · 2009. Ápr. 19. (V), 01.37
Ez nem egészen igaz. A memcachenek meg lehet mondani, hogy ha betelt a memória, ne dobja el a régieket, hanem az új entryre dobjon vissza hibát.

Ami a slab méretet illeti: tekintettel arra, hogy egy session bejegyzés kb lóf/2 méretű szok lenni azért ennek kellene működnie. Persze aki eszetlen mennyiségű adatot akar benne tartani, az megérdemli. A rendszergazda meg egyeztessen a fejlesztőkkel (vagy fordítva) hogy mit szeretnének csinálni és legyenek úgy megcsinálva a szerverek, hogy működjön.

Ez az egész egy döntési kérdés, nyilván ez sem tökéletes, de szerintem annál, hogy NFS-en vagy adatbázisban tároljuk a sessionöket, jobb lesz. Igazából kellene erre valami normális, specializált backendet írni de az sok C kód gépelését jelenti.

Nemsokára migrálunk majd valószínűleg Memcachere aztán jól meglátjuk.
39

...

Hodicska Gergely · 2009. Ápr. 19. (V), 02.37
Ez nem egészen igaz. A memcachenek meg lehet mondani, hogy ha betelt a memória, ne dobja el a régieket, hanem az új entryre dobjon vissza hibát.
Ok, de mire mész ezzel egy session esetén? ;)

Ami a slab méretet illeti: tekintettel arra, hogy egy session bejegyzés kb lóf/2 méretű szok lenni azért ennek kellene működnie.


Ezt írta inf3rno:
A memcacheben a sessionid lesz az azonosító, és elég sok dolog bele fog kerülni.


Plusz indexes ismerős mesélte, hogy szívtak már memcache esetén a slab méretek miatt, szóval nem légből kapott probléma.

Nemsokára migrálunk majd valószínűleg Memcachere aztán jól meglátjuk.
Jó esetben nem lesz vele gond, nálunk is Memcahce-ben vannak a sessionök (saját replikálással), és még nem volt para, pedig az érintett gépeke egyikén-másikán volt már többször restart is, szépen visszaszinkronizálódtak.
40

Félreértetted

inf · 2009. Ápr. 19. (V), 06.13
Azt hiszem félreértetted, amit írtam. Talán ebben én is egy kicsit hibás vagyok.

Ami bekerül a munkamenetbe az egy átlag user esetén iszonyatosan kevés adat. Inkább az adminoknál van szó nagyobb adatmennyiségről.
Arról már letettem, hogy szöveget memóriába mentsek, mert perceket kéne várni a garbage-re, hogy lementse az adatbázisba a session lejártakor, és nem szeretném, hogy néhány percre eltűnjön valami, majd újra megjelenjen. A garbaget meg emiatt nem szeretném sűrűbben futtatni.
Ami sok lenne, és bekerülne az az admin tevékenységének loggolása, viszont adminból nincsen olyan iszonyatosan sok, és nem hinném, hogy ebből megabájtokat össze lehetne rakni. Ezeket a munkamenet lejártakor raknám csak be a db-be, hogy ne kelljen minden egyes admin tevékenységhez db kérést írni. Ehhez is lehetne valami limitet szabni. Mondjuk a session mentése előtt megnézném, hogy mekkora a session hossza, és ha túl nagynak ítélem, akkor beraknám db-be az adatokat.

Default slab-re azt írták, hogy 48byte kulcs+flag és 40 byte adat. Ha bekapcsolom a tömörítést a set-nél, akkor elvileg lazán belefér egy mezei user összes adata egy cellába, tömörítés nélkül meg úgy határeset. De ha két cellát foglal el, akkor sem igazán számít, mert közelében sincsen annak a nagyságrendnek, hogy gondot okozzon. Valszeg inkább 2 cella lesz a serialize miatt.

Van valamilyen tapasztalatod azzal kapcsolatban, hogy a tömörítés mennyire éri meg?

(Egyébként kösz, hogy szóltál, jó ha tágul az ember látóköre.)