Php - data access concurrency testing
Maguk a PHP-s alkalmazások nem multithread-esek, az apache elég jól menedzseli ezt a témát, viszont az erőforrásoknál, amiket használnak már felléphetnek különböző concurrency-vel kapcsolatos hibák, mint lock contention, long term blocking, deadlock. Tudtok olyan költséghatékony módszerről, amivel ezekre lehet tesztelni az alkalmazást?
Úgy néztem a c# és java esetében van egy csomó külön megoldás és eszköz, a PHP-ben viszont a thread-ek hiánya miatt nem született ilyen, legalábbis én nem találtam. Hogyan lehetne ilyen eszközt készíteni, illetve hogyan kell kezelni az ilyen jellegű hibákat?
Mondok egy példát, pl lock contention akkor léphet fel, ha a kiszolgált tartalom mellé teszünk egy mezőt az adatbázisban, amin folyamatosan növeljük az olvasások számát. Így a népszerű cikkeknél ennek a mezőnek az írása folyamatosan lockolja a hozzáférést a tartalomhoz... Hogyan kerülhető el ez a probléma, és hogyan mutatható ki automatizált tesztekkel?
■ Úgy néztem a c# és java esetében van egy csomó külön megoldás és eszköz, a PHP-ben viszont a thread-ek hiánya miatt nem született ilyen, legalábbis én nem találtam. Hogyan lehetne ilyen eszközt készíteni, illetve hogyan kell kezelni az ilyen jellegű hibákat?
Mondok egy példát, pl lock contention akkor léphet fel, ha a kiszolgált tartalom mellé teszünk egy mezőt az adatbázisban, amin folyamatosan növeljük az olvasások számát. Így a népszerű cikkeknél ennek a mezőnek az írása folyamatosan lockolja a hozzáférést a tartalomhoz... Hogyan kerülhető el ez a probléma, és hogyan mutatható ki automatizált tesztekkel?
Deadlocks generally lead to
Ezek szerint ha mindig ugyanolyan sorrendben nyúlunk a kéréseinkben az erőforrásainkhoz, akkor a deadlock elkerülhető. Ez maximum ORM-el biztosítható, ha beteszünk hozzá egy modult, ami betartat egy bizonyos erőforrás sorrendet, de ezt kikényszeríteni elég kényelmetlen lehet. Ha kimutatható a dolog concurrency tesztekkel, akkor is el tudok képzelni olyan helyzetet, ahol a kód logikája megkívánja a sorrendet, amit megadtunk. Zsákutca, deadlock. :-)
Azt hiszem ez megint egy olyan téma, amiről könyveket lehetne írni, megoldása viszont nincsen... Azért kíváncsi vagyok kinek mi a tapasztalata a concurrencyvel?
A deadlock egy másik
Jó, de lock nélkül hogyan
Tegyük fel most, hogy ORM nélkül simán SQL-t küldök tranzakciókban az adatbázisnak... Az adatbázis legyen pgsql vagy mysql, kinek amelyik szimpatikusabb...
Ha SQL adatbázisról van szó,
Köszi, így már összeállt,
Közben nézem, nem csak a lock
Összességében ha nincs megfelelően bekonfigolva az adatbázis, vagy egy-egy trazakció, az okozhat gondokat alkalmazás szinten, szóval nem áll meg az az érvelés, hogy mindent bízzunk az adatbázisra, muszáj a concurrency-vel kapcsolatos dolgokat beállítani kézzel. Ha meg ezeket be kell állítani kézzel, akkor hibázhatunk, tehát szükség van tesztekre ezzel kapcsolatban. Concurrency tesztek írása ilyen jelenségekre meg PHP-ben távol áll az egyszerűtől szerintem.
Nem értem itt mit akarsz
Nem értem itt mit akarsz
Az alkalmazást akarom tesztelni, nem a keretrendszert, adatbázist, vagy drivert, amit használok. Az isolation level állítható, és úgy nézem, hogy pl keresésnél érdemesebb serializable-t használni, mert read committed esetén előfordulhat, hogy olyan találatok kerülnek fel a listára, amelyek nem is teljesítik a keresési feltételeket, mert éppen menet közben egy másik tranzakció módosította őket.
Olyasmire gondoltam, hogyha optimistic a locking, és nem read committed az isolation level, hanem serializable, akkor pl egy bankszámlán elveszhetnek pénzmozgások, ahogy azt a pgsql dokumentáció is írja. Nyilván nem azt szeretném tesztelni, hogy milyen isolation level beállítás van, hanem hogy az adott kód megfelelően reagál e a konkurrens kérésekre. Pl ha egy bankszámláról egyszerre vonok le 5000Ft-ot és teszek fel 6000-et, akkor az előző állapothoz képest a számla mindig 1000-es pluszban legyen.
Hát kicsiben valószínűleg nem éri meg. Ahogy néztem .NET-hez van egy CHESS nevű tool, ami multithread concurrency problémák azonosításában segít. Olyasmiről nem tudok, ami adatbázissal kapcsolatos, de 2 napja foglalkozom a dologgal...
Jelenleg még azt sem tudom, hogy olyan automatizált concurrency tesztet hogyan lehetne írni, aminél garantált, hogy egyik tranzakció egy bizonyos módon üközik a másikkal minden esetben, vagy többszöri futásnál legalább beazonosítható, hogy milyen jellegű ütközés okozza a hibát. Nagyon bonyolult téma...
Az isolation level állítható,
Inkább mutatnál olyat, ami
Hát ezt szerintem döntse el maga, hogy melyik a kisebbik rossz...
Ez így nem igaz, mert a kódommal tudok lockokat beállítani, és tudom változatni, hogy milyen isolation level-t használjon a tranzakció. Szóval ugyanúgy függhet a kódomtól a dolog.
De fussunk neki még egyszer. Én azt szeretném, hogy meghatározok egy data access layer-t, és ahhoz írok concurrency teszteket, amik a layer felületét használják, és teljesen függetlenek annak a megvalósításától. Így bármikor, amikor lecserélem a megvalósítást, a tesztek ugyanúgy használhatóak lesznek concurrency issuek kizárására. Ennyi a célom. Nekem tökmindegy, hogy ezeket az issue-kat az adatbázis oldja e meg, vagy a saját kódom, a teszteknek ehhez semmi köze. Csak azt kell biztosítaniuk, hogy meg vannak oldva ezek a problémák.
Én azt szeretném, hogy
Itt sincs szükség párhuzamos
A tesztelés az érdekes kérdés. Ugye egy multithread alkalmazásnál, meg itt is párhuzamosság okozza a hibákat, csak kicsit másképp... Ott a párhuzamosság a kódba van építve, itt meg a forgalomtól függ. Ugyanúgy random módon jön elő a probléma. Én úgy néztem, hogy a concurrency-vel foglalkozó eszközök, legalábbis az a kevés, ami van, az szinte mind úgy dolgozik, hogy a konkrét implementációt elemzi, és nem valami általános felületet ad a párhuzamos kérések tesztelésére. PHP-ben olyan eszközről tudok csak, amivel lehet szimulálni mondjuk egyszerre 1000 HTTP kérést, és meg lehet nézni vele, hogy nagy terhelésnél hogy skálázódik az oldal. Ennyi, amit tud, concurrency issue-k azonosítására nem igazán megfelelő. Nem tudom hogyan lehetne olyan test runner-t írni, ami egy időpontra időzít kéréseket, vagy amivel legalább sok hívás után el lehetne érni ilyesmit, és pontosan be lehetne azonosítani a sorrendet. Pl a chess-nél az van, hogy megpróbál többféle hívási sorrendet a párhuzamos kódnál, aztán ha valamelyiknél gond van, akkor azt jelzi, és egyértelműen vissza tudja játszani. De ugye ott a chess tud a thread-ekről, és mindenről, mert azok a kódba vannak építve. Itt, hogy felületet tesztelek, és nem implementációt, max azt lehet, hogy veszel két kérést, és a hívási idejüket tologatod egymáshoz képest, és így módosítod a sorrendet, hátha egyszer összeakad a kettő... Ezt mondjuk egy xdebug-hoz hozzákötve talán ki lehet számolni, hogy pontosan milyen kód milyen sorrendben hívva akadt össze a két kérésben. Szóval elméletileg lehetséges ilyet csinálni, gyakorlatilag meg nincs megfelelő test runner, ami párhuzamosan tudna kéréseket bonyolítani, mert nincs thread php-ben. Maximum a HTTP kérések szintjén lehet ilyet írni, az meg nem ugyanaz, mintha direktbe függvényeket vagy metódusokat hívnál, mert belekerülnek még fentebbi rétegek is. Talán lehet efölé a HTTP kéréses változat fölé heggeszteni egy test runner felületet, ami már képes fogadni objektumokat. Ehhez a szerializálást meg ugye a wakeup-ot kell megcsinálni ezeken az objektumokon.
Ide gyűjtöm a megoldásokat
- cURL multi - több process (párhuzamos http kérések)
- gearman - valszeg több thread
- pcntl_fork - több process
- exec - több process
- pthreads - több thread
Azt hiszem ez nagyjából egy teljes lista: http://code.hootsuite.com/parallel-processing-task-distribution-with-php/
Itt van komolyabb technikai leírás, hogy hogyan lehet kivitelezni: http://andrey.hristov.com/projects/php_stuff/pres/writing_parallel_apps_with_PHP.pdf
A phpunit-hoz van egy paratest nevű runner, ami párhuzamosan futtatja a unit test-eket. Ez nyilván nem az, amit akarok, de hasznos, mert felgyorsítja a tesztelést mind unit test-ek, mint integrációs tesztek terén.
Összességében lehetséges párhuzamosan programozni php-ben, szóval elméletben lehetséges olyan testcase-t írni, ami alkalmas olyan concurrency issuek tesztelésére, amit a közös erőforrások lockolása vagy kérések ütközése és esetleg mergelése okoz. Sajnos a gyakorlat azt mutatja, hogy senki nem csinált még ilyet, és hogy rengeteg váratlan probléma és gányolás árán lehetne csak megírni... Nekem erre jelenleg nincs meg a tudásom és a kapacitásom sem, hogy megtanuljam az ezzel kapcsolatos dolgokat. Pár helyre írtam ezzel kapcsolatban feature request-et, hátha bevállalja valaki, de erre sem látok sok esélyt, szóval erről ennyit...
Ezeket a zárolási problémákat
Egyetértek, azt ne akarjuk
Egyébként picit meglepett, amit inf3rno írt. Read committed mellett a reader akkor fogja csak látni az új sort, amikor azt becommitolták. És emellett mindig lát olyan verziót ami az adott pillanatban valid, ez az mvcc lényege. Ergo a readernek nem kell várjon a writerre.
Egyébként picit meglepett,
Nem vagyok benne biztos, hogy ez minden adatbázisra igaz. Bár kevés a tapasztalatom vele, csak az alapján írtam, amiket olvastam a témában, pl: Database Locking: What it is, Why it Matters and What to do About it
Btw. nekem egyáltalán nem tűnik 1+1 szintű problémának az, hogyha rosszul van megírva az alkalmazás, akkor deadlockot okozhat, vagy rosszul skálázódik... Érveket várok! ;-)
Azt olvastam, hogy a deadlock ellen védettek az adatbázisok, de gondolom a fájlrendszer nem az... Ha van két controller action-öm, amik fordított sorrendben lockolnak két fájlt, akkor az kapásból okozhat deadlock-ot... Egy ilyen hibát hogyan kezelek, egyáltalán mit lát a user? Csak vár-vár, aztán az egyik script elszáll timout-al mindenféle magyarázat nélkül, az adatok, amiket begépelt meg elvesznek...
Nem vagyok benne biztos, hogy
Az, hogy hogy skálázódik, az performancia probléma, és ennek megoldása feladatfüggő. Általánosságban azt lehet elmondani, amit múltkor is írtam: ne akarjunk egy erőforrást párhuzamosan írni. Ahol lehet, használjunk aszinkron műveleteket, azok mentén jól lehet skálázni stb. De ez tényleg elég általános.
Egyébként pedig a párhuzamos file írkálás webről szerintem eléggé antipattern a fentiek miatt. Ennél az sokkal jobb, ha egy queueba rámolod az ilyen jellegű requesteket, amiket valami háttérfolyamattal tudsz feldolgozni, és a folyamat eredményét tudod pollozni, vagy valami ilyesmi. Úgy adott esetben lock sem kell, ráadásul kontrollált keretek között párhuzamosítható.
Tudnál példákat mondani, hogy
Nem muszáj 2 fájl példájánál maradni, legyen az egyik erőforrás fájl, a másik meg adatbázis. Mondjuk kép feltöltés, album szerkesztés, törlés, stb... esetében elfordulhat ez a kombináció... Itt is két erőforrás van, és ha két controller-ben fordított sorrendben lockoljuk őket, akkor az deadlock-ot okozhat. Ez is ugyanúgy fájlrendszeres probléma...
A loggolás szintén egy érdekes kérdés, mert bárhova loggolsz, az lehet szűk keresztmetszet egy oldalnál... PHP-ban nem nagyon van lehetőség arra, hogy rábízd az ilyesmi egy deamon-ra úgy, hogy nem is foglalkozol azzal, hogy sikerült e loggolni, vagy nem, és csak a kérést küldöd el neki...
Tudnál példákat mondani, hogy
A skálázódáshoz: ahogy fentebb írtam, valami teljesítmény méréshez használatos toollal tudod kideríteni. Én használtam régebben siege-t, és JMetert, utóbbi azért lényegesen többet tud. Ebből megkapod hogyan skálázódik, hogy mi okozza magát az esetleges rossz skálázódást, azt meg leginkább valami profilerrel, kódbogarászással lehet megtalálni. PHP kapcsán ilyesmivel nem vagyok képben. Általánosságban azt lehet elmondani, hogy az olvasás jól skálázható, az írás nem. Ez CPU/memória szinttől adatbázisig így van. Tehát ez nem nyelvfüggő dolog.
Ez kód probléma, semmi köze a
Persze, hogy kód probléma, ezért kell automatizált teszt, vagy valamilyen tool rá, hogy kimutassa...
Semmi. Közben átgondoltam, a loggolással úgy általánosságban csak akkor lehet baj, ha pessimistic lock-ot használsz az írásához. Akkor baromi rosszul fog skálázódni...
A fájlrendszeres problémára
Ezen kívül még vannak olyan fájlrendszerek, amiknél lehetséges fájlrendszer tranzakciókat használni. Ez mondjuk nagyon ritka még szerintem.
A tesztelés részéhez még visszatérek később, most sajnos nincs időm rá. Egyébként is elakadtam vele, mert nem találok megfelelő parallel test runner-t, ami minden platformon és különösebb telepítgetés, fordítgatás nélkül is elmegy.
os-php-multitask
running-multiple-processes-in-php
simple-async-php-without-pcntl-stuff
ParallelProcessing
node/view/254
adapt-php-parallel-execution-function-for-windows
Csak azért írom fel őket, hogy később ne kelljen keresgélni megint... Szinte mindegyik proc_open-el meg aszinkron streameléssel variál valamit, de még nem teljesen értem, nem volt időm tanulmányozni a logikáját.
Tisztelt Kolléga
Pontosan. Az ütközést a párhuzamos munka okozza, mármint az egyidejű írási kérés. Ez akkor gond, ha jó eredmény csak soros feldolgozás esetén lehetséges. Megoldás, nem tesszük lehetővé a párhuzamos írást. A zárolás éppen a sorba rendezést szolgálja. Minden írási feladat konkurencia nélkül futhat, a többi addig vár. Rejtélyes, hogyan lett ebből a tiszta képből teljes párhuzamosítás.
Inf3rno 28:
A már kihalt "Novell" op.rendszerben volt ilyen, 20 évvel ezelőtt. Adatbázis és tranzakció kezelés hiányában használhattad tetszőleges fájlokra. Lehet, valamelyik Linux,BSD ismét feltalálta. Szerintem jobb adatbázissal dolgozni.
Blaze 27:
Lehet így is. A háttérben futó program egy "démon", azzal kell kommunikálni. A "démon" feladata a sorba rendezés, nem a miénk. Adatok átküldve szabvány serializált formában, némi kódolt algoritmussal vegyítve. Értesítés a feldolgozásról, polling vagy call-back ... Nem egyszerű.
Pontosan. Az ütközést a
Az, amit írsz a pessimistic locking, és azért nem használják, mert nagyon rossul skálázható. Minimális forgalom felett a látogatóid elkezdenek várni a lockok feloldására, és nagyon belassul az oldal...
Nem most inkább windows közeli rendszereknél divat:
http://msdn.microsoft.com/en-us/magazine/cc163388.aspx
Persze a daemonok megoldás, de ahhoz általában dedicated server kell, és ha már daemonokat kell használni, és van egy dedicated server-em, akkor fix, hogy nem php lesz a nyelv, amit használni fogok, hanem valami olyan, amiben könnyen lehet ilyesmit írni, mondjuk nodejs.
Nem tudható milyen terhelésre
Egyébként a zárolás nem azért van hogy az olvasási műveleteket gátolja. Tudomásom szerint nyitott tranzakció alatt gond nélkül olvasható az adatbázis. A zárolás megoldható úgy is, hogy minden művelet lehetetlenné váljon, de úgy is, hogy csak a konkurens írást akadályozza. Egyszer próbáltam ki a "lock table"-t mysql 5.akárhánynál, vagy nem olvastam figyelmesen vagy nem említik, de utána másik felhasználó nem fért hozzá az adatbázishoz sem. Ezt tényleg ne.
Egyébként eset függő mit lehet használni: stackoverflow locking
A Microsoft-ot megnéztem. API szinten diszkrét fájl műveleteket "véd". Ez nem azonos az egykori Novell tudásával. Ott az volt a lényeg, a fájlok írása esett tranzakciós védelem alá. Például, egy nagyméretű text fájlnál írhattál a közepébe, meg mindenfelé, ez mind véglegesíthető vagy visszagörgethető volt.
Eddig a peldaid rosszak...
Osszegezve, lockolast szinte soha sehova, csak ha meg tudod indokolni (eddig nagyon ritkan lattam en magam olyat, ahova ez kellett. Olyat szoktam latni, ahol a hozza nem ertes miatt lockoltak, mert pl. a megfelelo eljarast nem ismertek). Az izolacios szintekhez se nyulj hozza lecci. Mind a 4-nek megvan a hatranya. 99,9999999999%-ban az alap repeatable read a legjobb (legkisebb rossz, bar nem olyan rossz az).
Osszegezve, lockolast szinte
Én elég sűrűn láttam olyat, hogy select for update.
Én úgy néztem, hogy érdemes kérés típustól függően megválasztani az izolációs szintet. Mondjuk ha írni akarsz, akkor jó az alap read committed, ha meg keresni, akkor jobb a serializable. Mást pgsql nem tud, legalábbis a 8.4-es verzió, amit most használok.
Ezt kifejtenéd?
Egyszerre több táblát kell
(és milyen lockról beszélünk? Tábla? Sor? Egyéb?)
Egyszerre több táblát kell
(és milyen lockról beszélünk? Tábla? Sor? Egyéb?)
Lock az mindenképp lesz, inkább arról volt szó eddig, hogy kézzel lockoljunk, vagy konfigoljuk be úgy az adatbázist, hogy ő csinálja meg helyettünk a lockot egy bizonyos módon, stb... Az, hogy éppen milyen lockról van szó teljesen kérés függő.
lock
Nekem ebből az jött le, hogy úgy általában elutasítja a lockolást, ezért kérdeztem.
Hogy lock parancsot nem használunk sűrűn, az egy másik téma.
Ja bocs, benéztem, azt hittem
Ha olyan a feladat, hogy van
Meg hát az igény a lockra
Ezzel vitatkoznék. Ha aggregált értéket tárolsz egy táblában, már szükség is van rá. Ha aszinkron dolgozod fel a requesteket, akkor is fennáll a probléma, mivel lazán lehet egy időben később elküldött requestben régebbi verzió (vagyis régebbi állapot alapján küldte a client a requestet)
Ezt a wiki oldalt most találtam és bár csak bele-bele olvasgattam, egész jónak tűnik.
Ha aggregált értéket tárolsz
Persze, kb ugyanezt írják pgsql manualban is.
Majd még teszek fel blogmarkokat ezzel kapcsolatban, van 1-2 jó anyag, csak még át kell rágnom magam rajtuk...
Nem teljesen értem mire
A fentebb írt requestek particionálását egyébként a jelenlegi projectemen használjuk, és nagyban megkönnyíti a munkánkat. Tény, hogy nem db-vel kapcsolatban (hanem szálakhoz irányítjuk eventek feldolgozását) meg az is, hogy az egyes eventekhez kapcsolódó entitások semmilyen relációban nem állnak egymással, tehát egyszerűbb a terep, mint egy relációs adatbázisnál. De az elv működik.
Igazat adok neked, amennyiben
Egy optimistic lock version fielddel szerintem annyira kicsi overheadet jelent, hogy minden más esetben érdemes használni (no nem minden táblában, hanem aggregatekben gondolkodva csak az aggregate root táblájába, de ez már más téma).
Terhelés
A zárak problémáit nem
ab
A gond nem ezzel a részével
A probléma ott van, hogy pl egy olyat hogyan csinálsz, hogy
pcntl-el lehetne, de az csak linux-nál működik...
minden másnál meg valahogy szerializálni kell az aktuális szituációt, és úgy eljuttatni a futtatókörnyezetbe...
A php-t nem igazán párhuzamos
Hát agyalok rajta...
Alapból ilyesmire gondoltam, mint kezdetleges concurrency test-re:
Erre most nekem nincs kapacitásom. A token-get-all-al megoldható a parsolás, és az újra építés, és ha elég okosra megírod a parsert, akkor szinte bármilyen szintaxisa lehet a tesztednek...
Párhuzamosítás nélkül
A pthreads-szel tudsz
Ha onnan közelíted a dolgot, hogy a php kódod a valóságban teljesen izoláltan fog futni, és a db-n keresztül lehet rá hatással egy másik php process, nézheted onnan is, hogy a kódod védett, ha ezt kizárod az adott request egészére, vagy egy adott blokkra. Lockolás, izoláció, vagy amire szükséged van. Ezesetben elég az, hogy azt vizsgálod tesztből, hogy a kódod meghívja/elengedi a várt pontokon a lockot, beállítja az isolation levelt stb, hisz azok megbízhatóak. Innen vizsgálva egyszerűbb a feladat. Biztos nem lenne elég ez a megközelítés? Persze ha neked kell megvalósítanod magát a szinkronizálást, akkor sok lehetőséged nincs a tesztelésére...
Én pont ezt szeretném
A pthreads-en kívül még a proc_open, amit még visszaveszek lehetséges megoldások közé. Az tud külön fájlok nélkül php kódot futtatni, és lehet vele kommunikálni pipe-on keresztül. Ami hátránya, hogy úgy egyébként semmit nem tud a külvilágról. Ha a pthreads is ugyanilyen, tehát nem tudok változókat átadni neki szerializálás nélkül, akkor egyszerűbb a proc_open-el kezdeni. Ezt még ellenőrizni fogom.
A tesztelést úgy gondoltam, hogy csak megadom a 2 task-et, automatikusan többször lefuttatom rájuk a tesztet eltérő wait időközökkel, és ha valahol gond van, akkor annak a scenarionak az adatait, hívási sorrendjeit valahogy külön visszaadom. Ez mondjuk elég fapados, de ennél komolyabbat nem hiszem, hogy tudnék csinálni, ha nem kezdek beleírni alacsonyabb absztrakciós szintű kódokba...
Jó a pthreads nyert
Olvastam még olyat, hogy 5.3.x-nél nem elég stabil, inkább 5.4 felett ajánlják. Hát megnézem... Most 5.3.28-ra kellene valami...
Közben megtaláltam, hogy körülbelül mi kell az aszinkron híváshoz: Async::call
Az aszinkron hívás nem elég.
Valahogy így néz ki:
Egyelőre valami ismeretlen
Na közben összejött,
A php.exe-vel viszont tudok normálisan dolgozni, a probléma csak a php-cgi.exe-t érinti... Valószínűleg van megoldása, de most hanyagoljuk... Összességében hasonlóan a proc_open-es megoldáshoz nem tud valami sokat, ugyanúgy muszáj szerializálni mindent, amit át akarok küldeni, pl Closure-t egyáltalán nem tudok átvinni (egyelőre).
update:
Jah, bug volt, javította a srác elvileg...
Elvileg van mód dolgok megosztására szerializálás nélkül, a phpthreads objectek sosem kerülnek szerializálásra, tehát ha egy ilyenbe tesztek egy erőforrást, closure-t, vagy bármi mást, akkor azt át lehet adni a többi thread-nek anélkül, hogy szerializálással kellene szenvedni... Ezt még csekkolom...
public function
concurrentExecution
egymáshoz képest milyen delay-el tolja el a konkurrens kéréseket nanosleep-el szeretném változtatni több egymás utáni futásnál. Így elvileg lehet tologatni egymáshoz képest a thread-ek futását, és el lehet érni, hogy bizonyos beállításoknál összeakadjanak a lockok. Szóval nem akarom kézzel szinkronizálni a teszteket, mert ahhoz szerintem szét kéne bontanom az repository-k kódját, és olyan event-eket betenni, amik jelzik, hogy mikor jön a másik szál. Persze lehet, hogy valamit félreértek, javíts ki, ha tévednék...(A a
concurrentExecution
-t valószínűleg nem tudom megvalósítani a fenti formában, de azért megpróbálok valami hasonló, könnyen érthető interface-t csinálni a dolognak.)Nem determinisztikus
Ezzel az a baj, hogy a teszt
Igen, ez sajnos így van, de ezen kívül szerintem csak úgy lehetne megoldani, hogy manuálisan vagy parsolással a kódok megfelelő részébe eventeket csempészek. Hmm, azt hiszem, hogy csinálok egy keretrendszert resource-ok kezelésére, és ott a test scenario-ba bármit belerakhatok, ami csak tetszik. Így magát az alkalmazást nem kell tesztelni concurrency-re, csak a concurrency manager-t.
Valami ilyesmi felületre gondoltam (a példa gagyi):
Imho ez egy pár napos projekt keretében megvalósítható.
Sajnos most nincs időm java-t nézegetni. :S Egyébként ja, alapból Thread-el rendelkező nyelveknél teljesen más a helyzet, ott megvannak a megfelelő eszközök bármi ilyesmire.
update:
Közben megtaláltam, hogy magát a problémát distributed transaction-nek nevezik. Nyilván szükség van egy filesystem transaction-re is, illetve szükség van valamilyen distributed transaction mintára, ami a két tranzakciót szinkronban tartja. Ez két külön rendszert igényel. A teszteléshez a pthreads teljesen jó mindkettőre... Egy thread-ben indítok egy tranzakciót, a másikban egy másikat, aztán összehangolom őket event-ekkel, és próbálgatom, hogy hol lehetnek hibák. Ezek alapján nincs is szükség külön teszt rendszerre, jó úgy, ahogy írtad, hogy eventekkel meg szál szinkronizációval...
Köszi a segítséget! Nélküled nem hiszem, hogy eljutottam volna idáig... :-)
Amit előbb írtam (proxy),
Yepp :-)Agyalok most a fájl
Agyalok most a fájl - adatbázis témán, és gondban vagyok.
Egy hétköznapi példa, meg akarod változtatni a profile picture-t fácsén, maga a kép fájlrendszerben van tárolva a neve meg be van téve a user táblába.
A multithread vagy valami hasonló megoldaná ezt a szétválasztási problémát:
Tök érdekes mindenesetre, hogy kapásból előkerültek a thread-ek, mint megoldás. Ahogy nézem coroutine-al szintén megoldható a dolog, felesleges thread-et alkalmazni hozzá...
A váltogatás egyik task-ről a másikra, meg egymás bevárása elvileg megoldható simán coroutine-al. Ha lemegyünk egy-egy kérés szintjére, akkor nincs is szükség thread-ekre, hogy concurrency-t szimuláljunk, bőven elég a multitask...
A probléma max az lehet, hogy mennyire kemény dió a doctrine driver-ébe beleírni... Esetleg lehetne inkább csak magába a PDO driverébe, amit használ, ott simán lehet loggolni 1-1 kérést, én már csináltam ilyet. Ja, gondolom te a PDO-ra gondoltál driver néven...
Alakul a molekula... :-)
Ja, szóval az elejétől kezdve azt javasoltad, hogy cooperative multitasking-et toljak, és tegyek breakpoint-okat a statement-ek közé, amiknél át tud váltani a másik task-re a php. Jóvan, lassan esett le, de ja, ez tényleg működőképes megoldás. Ha mellé még csinálnok egy distributed transaction implementációt valami egyszerű módon, akkor sínen van a dolog. Le lehet választani egy külön rétegbe a problémát, ahol jól tesztelve meg is lehet oldani anélkül, hogy magasabb absztrakciós szinten hozzá kellene nyúlnom bármihez is, vagy tesztelnem kellene concurrency-re.
Létre is hoztam egy repo-t a
Az a baj a fenti cooperative
Valahogy így nézne ki callback hell-el:
update: megnéztem a lehetőségeket, nem látom értelmét energiát belefektetni, ugyanis a generátorok php 5.5-től teljesen ugyanezt tudják. Annyi a különbség, hogy a töréspontokon nem kell új closure-t létrehozni, hanem elég egy yield-et kitenni, hogy tudja a rendszer, hogy ott most szünetet tart, és később majd onnan folytatja a függvény futását.
Csak annyit szeretnék
Másik szálakban látom nézegeted az MQ-kat, ha jól láttam az ActiveMQ még nem volt. Én ezt konkrétan még nem próbáltam, csak más JMS implementációkat, de ennek van php kliense is, azért említem. Tranzakcionális, sőt tud XA-t is, bár azt nem tudom, hogy a php ehhez nyújt-e supportot.
Ha ilyen feature-ökre van szükséged, és ha ebben a domainben mozogsz - nem csak a példád jön innen - én elgondolkodnék, hogy másra nyergeljek át php helyett. És amúgy is, amik lejönnek a postjaidból hogy mik után olvasgatsz, rendesen feszítik itt-ott a php kereteit :) off-peroff :)
A php most ehhez a projekthez
Köszi, megnézem azt is. MQ használata emiatt a probléma miatt szerintem erősen ágyúval verébre jellegű. Gondoltam már rá, én is emiatt néztem meg őket, mert valahol írták, de ide felesleges. Máshova hasznát fogom venni...
A pthreads nekem egyáltalán nem tűnik bonyolultnak, csak sima start meg join van benne, ami azért nem egy atomreaktor... A szinkronizálás részén el fogok még gondolkodni.
Köszi, megnézem azt is. MQ