CQRS és a felhő
Miközben folyik a MiniStock fejlesztése, írnék azért pár szót arról is, miért fontos ez egyáltalán. Kapunk egy új architektúrát, de miért nem jó a régi?
Emlékszem, mikor annak idején először hallottam a SOA-ról, hamar lelkesedni kezdtem az újításért, de viszonylag hamar felmerült ott is a kérdés: mik azok a lehetőségek, amiket ez megnyit? Milyen projekt- és informatikai környezetben tud többet nyújtani, mint az addig használtak, és mik azok a feltételek, ahol csak időpocsékolás lenne?
A választ ezekre a kérdésekre persze a tapasztalatok hozták meg. Miután már a harmadik-negyedik SOA-szerű projekten is túljutottam, és láttam, hogy a gyönyörű elvek
miért nem használhatók a gyakorlatban. Vagy miután lelkes SOA szakértőként és –evangelizátorként belekötöttem az élő fába is a fiatalon meghalt Architektúra Fórumon, de zavarba estem mikor a projekten a junior megkérdőjelezte a négy alapelv értelmességét. Mikor lelkesen vártam az első ESB referenciaarchitektúrákat hogy hogyan is kéne elképzelni ezt, és ámulattal lepődtem meg, mikor az érett ESB implementációkat felfedeztem az Azure keretrendszer részeként.
És mire idáig eljutottam, jött az új buzzword, a CQRS. Felejtsünk el mindent, amit szervízhomlokzatokról, DTO-król, üzleti szolgáltatásokról tudunk, itt az új divat, ami jobb lesz.
MiniStock: egyre nő
Mikor legutóbb arról postoltam, hogy publikus lett a MiniStock alkalmazás, annak elsősorban az volt a motivációja, hogy nehogy a CodePlex törölje a workspace-t. Ismerem magam, tisztában voltam vele, hogy ennyi volt, soha többet egy bit kód nem kerül bele. És a post utáni hetek hajtása ezt is igazolta – tényleg hozzá se nyúltam hetekig.
Ezzel szemben engem is meglepett, hogy végül mégis tudtam foglalkozni vele. Gyakorlatilag a protokoll pozitív ága kész, van hozzá egy egyszerű webes kliens amivel lehet ügyfelek adatait piszkálni (életem első jquery-s, vagy asp.net mvc-s fejlesztése), azt lehet mondani, hogy a proof of concept fázist lezártam. Ilyenkor szoktam átadni a fejlesztőknek, hogy kezdhetik az üzleti funkcionalitást implementálni rajta.
Mit tud most?
- Eseményvezérelt architektúra: ugyan a felületet még lehet felhasználóbarátabbá tenni, de már most is atomi műveleteket küldök a szerver felé, nem bazinagy “SaveCustomer”-eket.
- CQRS megvalósítás (gyerekcipőben): az eseményeket egy aszinkron command feldolgozó nagyágyú valósítja meg, utána ennek eredményét perzisztáljuk egy relációs adatbázisban, ahonnan a kliens le tudja kérdezni az aktuális állapotot. Van még nyitott kérdés, sok.
- Skálázható, lazán csatolt szerveroldal: az eseményeket több feldolgozó node-re tudom szétosztani, minden node-nek elég csak a saját eseményeit ismerni (plugin-szerű működés lehetséges)
- Protokoll megvalósítás: megy az üzenet routing feldolgozó és perzisztáló node-ok között, a processzor node már kezeli az újraindítást is (perzisztens állapotú), hibaüzenetet vissza tudok küldeni a kliensnek.
- UI megvalósítás: bár jquery, de működik a forgalom minimalizálás
- Dokumentáció (csírákban): architektúradiagrammok, a főbb komponensek leírása felkerült a codeplex site-ra.
- Host processzek: egyelőre windows service-k, de majd lesz azure host is
És hogy min agyalok még?
- Mindenképp csiszolni kell a feldolgozó processzt, hogy a fault kezelésre megnyugtató választ tudjak adni. Az összetett műveletek kezelése is nyitott kérdés még (http://ministock.codeplex.com/discussions/351172).
- Át kell gondolni a teljes adathalmazra vonatkozó validációkat – pl. az “Ügyfélnévnek egyedinek kell lenni” típusút, hogy ezt memóriában, vagy a query adatbázisban célszerű ellenőrizni (http://ministock.codeplex.com/workitem/17765)
- Kell egy teljesítménytesztelés és optimalizálás, mielőtt továbbmegyek
- Érdemes lesz megvalósítani még pár entitást, hogy az aggregátumok közti kapcsolatokat is lássam a rendszerben (pl. az összetett műveletekhez is)
- Szofisztikálni kell a generikus query interfészt, hogy szűrhető és lapozható legyen, a kliens ui-t módosítani kell hogy használja őket.
És még millió egyéb gondolatom van vele kapcsolatban, amiket a codeplex site-n gyűjtök is, de most ezek a legfontosabbak.
Ki tudja, talán egy hónap múlva már ezekre is kapok választ. Az mindenesetre bíztató, hogy az elkövetkező hetekben éppúgy nem lesz időm foglalkozni vele, mint ahogy múlt hónap elején se volt…
what keeps me busy…
Érzem, hogy nem volt túl aktív a blog mostanában. Elsősorban azért, mert más elfoglaltságaim akadtak (vezetőfejlesztés, házasságszervezés, konzulálás, stb). Másrészt pedig egy hobbiprojektet pofozgattam eddig, most érte el azt a szintet hogy publikálható.
Mindenkinek sok szeretettel: http://ministock.codeplex.com
Steve Jobs 1955-2011
http://www.apple.com/stevejobs/
Hozzáfűzni nem lehet sokat. Rest in peace, Steve.
Martin Fowler: The LMAX Architecture
http://martinfowler.com/articles/lmax.html
Fowler egy esettanulmány kapcsán elemzi az esemény-alapú architektúrákat, amiket a CQRS cikkben én is említettem. Érdekes látni egy ilyet a gyakorlatban is.
CQRS
A Windows Azure blogon találkoztam először a CQRS fogalmával, ami a Command-Query Responsibility Segregation rövidítése, egy új architekturális minta, ami azt ígéri, hogy a hagyományos architektúrák ezer baját orvosolja. Felkeltette az érdeklődésemet, mint minden új buzzword, és elkezdtem utánaolvasni a http://cqrsinfo.com weblapon.
A kérdés: ez most valami új, vagy csak kapott egy új nevet egy már meglévő architektúra? Boncoljuk kicsit meg, miről is van szó:
Maga a command-query responsibility segregation elv arról szól, hogy a műveleteket egyértelműen azonosítsuk be: egy művelet vagy lekérdezi a rendszer állapotát, vagy módosítja azt. Ne keverjük őket, azaz például a módosítás ne adja vissza a frissített adatokat, csak nyugtázza a változást.
Ennek az a kellemes következménye, hogy külön feldolgozó úton történhet a lekérdezések és módosítások végrehajtása. A rendszert tervezhetjük olyanra például, hogy a lekérdezések közvetlenül adatbázisból dolgozzanak, kihagyva a domain mappinget és validációt (hiszen ha ez a módosításoknál megvan, azok eredménye mindig egy valid domain lesz, a lekérdezés eredménye meg úgyis DTO, amire le kéne képezni a domaint – minek csináljunk felesleges lépéseket?). Eleinte persze lehet hogy kényelmetlen érzés kihagyni a nagybetűs Üzleti Logikát (mert úgy tanultuk hogy az kell), de ha valaki már meglépte azt, hogy a riporting services nem SOAP adatforrásból dolgozik hanem az adatbázisra épített view-kből, akkor igaziból már így dolgozik, ezt kell kiterjesztenie a teljes rendszerre.
A tudás persze itt még nem áll meg: mi lenne, ha a gigászi domain modellt, és a ráépülő CRUD logikát is átgondolnánk? Az üzleti műveletek jellemzően nem préselhetők be a CRUD-ba: nem UpdateOrder műveleteink lesznek, hanem CreateOrder (létrehozáskor), SubmitOrder (a rendelés elküldésekor), ShipOrder (teljesítéskor). Mégis, a szerveroldalon gyakran GetOrderById, CreateOrder, UpdateOrder, DeleteOrder műveleteink vannak.
Jó ez? Nem. Kimondottan SOA antipattern. Valljuk be: hogy mégis ezt használjuk, az inkább a kényelem mint az átgondolt tervezés eredménye.
A gigamodell kompozit entitásai helyett pedig lehet, hogy ezeket jobb lenne osztály szinten megtenni (osztály alatt pedig olyasvalakit értsünk, aki viszonylag pici, hiszen csak egy felelősségi köre van. Valami minimális, de összetartozó üzleti tudás kezelése például).
Ha mondjuk létrehoztuk a megrendelést, akkor a számlázási címet alighanem egy Address típusú osztály fogja tárolni. A hagyományos SOA megközelítés az, hogy a cím változása a teljes rendelés megváltozása (üzletileg teljes dokumentumokat kezelünk), ehelyett engedjük csak a cím megváltoztatását, legyen a műveletünk az UpdateShippingAddress.
Figyelem, itt kezdünk eltávolodni a SOA-tól.
Ha kis entitásokra esik szét a domain modellünk, akkor azokat akár tárolhatjuk historizálva is, azaz az aktuális verzió helyett tároljuk inkább azt, mi történik az elemmel a létrehozás óta. Mondjuk (esemény, változás) halmazt, amiből lejátszhatjuk a teljes élettartamot. Persze ehhez tárolhatunk snapshotokat hogy egyszerűbb legyen az aktuális állapotot lekérdezni, de ez opcionális.
Ez a leírás szerint azért jó, mert additív lesz a tárolásunk, az adatbázisban csak insertek lesznek, amitől javul a teljesítmény (pl. azért, mert nem lesznek konkurens frissítések). Persze a snapshot készítésnél lesznek, ezért annak a frissítését érdemes optimalizálni. És nyilván ez az adatmennyiség nagyobb lehet, mintha csak az aktuális verziót mentenénk. Miért éri meg?
[TBD]
(Nem azért mert lusta vagyok, hanem mert a cqrsinfo.com szerzője se tudja egyértelműen megmagyarázni. Mindenféle üzleti követelményekre vezeti vissza, de ha követelmény volt az időbeli viselkedés követése, akkor azért eddig is megcsináltuk a temporal objecteket, tehát nagy újdonságot nem jelent az eventek mentése. Ahol meg nincs ilyen jellegű igény, ott a szerző szerint is túl költséges lehet az ilyenfajta tárolás. Ráadásul kifejezetten ellene megy annak a CQRS elvnek, hogy a lekérdező műveletek domain tudás nélkül előállíthatóak legyenek, hiszen az események visszajátszása domain logika)
Hol találkozik a két elképzelés, a CQRS és az esemény-alapú mentés? A vázolt architektúra lényege, hogy duplázzuk az adatbázist is, a change műveletek mindig eseményeket mentenek csak, a read műveletek pedig mindig egy rendesen megtervezett, relációs adatbázison operálnak. Azaz a domain-t kettéosztjuk: a change műveleteken üzleti logikában építjük fel (és számolunk vele, validálunk, stb)., de a perzisztencia rétegben csak gyengén tipizált eseményeket tárolunk. A query műveleteken pedig a domain az adatbázis szerkezet révén adott, onnan közvetlenül olvassuk fel az eredményt.
A kettő között nyilván kell egy mapping, azaz az eseményeket le kell játszani a query adatbázison is. A cikk írója szerint ezt egyszerűbb megvalósítani, mint kapásból ezt megtenni a change műveletekkor – és annyi igazság lehet benne, hogy ezen a ponton a változtatások már sorosodtak, azaz konkurenciával nem kell foglalkoznunk. A probléma ezzel persze az, hogy a változások feldolgozása nem feltétlenül tranzakcionális, azaz elképzelhető, hogy az eventet már lementettük, de még nem vezettük át a read művelet előtt. Másik probléma meg az, hogy ha a domain változik, akkor azt két helyen kell átvezetni – a write oldalon az üzleti logikában, query oldalon pedig az adatbázis szerkezetben. És míg hagyományos mosóporral az első smoke teszten kijön (már akár unit teszteléskor is hibát dob az OR mapping tool ha szét vagyunk csúszva), itt csak komoly integrációs teszteléssel tudjuk felderíteni, ha valami viszonylag ritkán használt mezőnél gond van.
Konklúzió: bár a cqrsinfo.com szerzőjének tudása számomra némileg hézagosnak tűnik (az indoklásai jellemzően értelmetlenek, rossz környezetben idéz mintákat, hamis feltevések alapján von le következtetéseket, stb.), az eredményül kapott architektúra azért elgondolkodtató. Nem biztos, hogy holnap átírom ilyenre a projektet, de arra mindenképpen jó, hogy ad egy másik nézőpontot, amiből megvizsgálhatjuk a belénk kövesedett alapértelmezett “optimális” megoldásokat – talán annyira nem is ideálisak.
Másrészt pedig, ha egyszer olyan rendszert kell építenünk ahová passzol (azaz ahol fontos követelmény a tranzakciók időbeni visszakereshetősége, neadjisten visszagörgethetősége, és cserébe nem probléma a megnövekedett tárhely és a módosítások késleltetett érvényre jutása), máris van egy konzerv megoldásunk rá.
Havi státusz?
Eszt a naplót aszért kesztem írni, mert egy különös felvilágosítás követkesztében Valaki amikor becsúsztam többrendbeli figyelmeztetésre hívta fel a következőkben. Hogy mi van velem. Mert ezt írni kell.
Mostanság Azure fejlesztések vezetésével foglalkozom. Harmadik iteráció, a fejlesztés kezd visszaterelődni a saját medrébe (van egy olyan fixa ideám, hogy mikor valami új dolgot tanulunk, elsőre lelkesedésből sikerülni fog, másodszorra elbízzuk magunkat tehát bukta, és a harmadik nekifutás lesz az, mikor kezd kialakulni a tudás – már tudunk tanulni a hibákból, építeni a tapasztalatokra, stb). Itt tartok most, még messze a rutinos vén rókaságtól, de remélhetőleg túl az első nagy pofáraeséseken.
Újdonsült érzés a frusztráció a platform eszközökkel: a Microsoft valami miatt ezt nagyon elzúrta. Rendes debugger csak a VS Ultimate-ben van, ami semmilyen előfizetéses vagy partneri csomagnak nem része, a fejlesztőnkénti 2M Ft (sic!) pedig kicsit soknak tűnik. És máshogy nem is hajlandók támogatni a deployment hibakeresést, a legtöbb amit (Azure fejlesztői partnerként, hivatalos support megkeresésre) hallottunk: “Tegyétek fel az időlimites próbaverziót”.
Az Azure SDK verzióváltásáról jellemzően onnan értesülünk, hogy nem működik az upload. Még az Azure portálon se találtam linket arról, hogy mi az aktuális verzió, mikor tervezik a következő release-t, és mi változott. Tudtam hogy az 1.3-ast használjuk, de azt, hogy kijött az 1.4-es, csak onnan tudtam meg, hogy rafináltan rágugliztam a következő verzióra. Durva, nem?
Az evangelizációra hallgatva átraktuk a webalkalmazásunkat két lábon futóra. Azonnal behalt a session kezelés. Rövid kutakodás után rá kellett jönnöm, hogy egyáltalán nincs támogatott osztott session kezelési megoldásuk az SDK-ban. Példakódokra meg fórumokra mutogatnak, meg “igazán egyszerűen csinálhatsz magadnak egyet” linkeket küldözgetnek, mint a legrosszabb opensource-os világban.
Szóval egyelőre a tokom kivan az új Microsofttal (abból gondolom hogy új, hogy régebben azért ilyen szintű amatőrizmust / szemtelenséget nem engedtek meg maguknak. Viszonylag jól támogatták a fejlesztőket, a .NET 2.0 SDK kerek és jól kitalált volt, örültek hogy használjuk és terjed a platform. Ez a hozzáállás valahogy eltűnt).
Másrészt viszont lassan de biztosan kialakul bennem a saját agilis módszertanom, helyükre tudom tenni a különböző okosságokat, látom az előnyeit, kezdem kitanulni hogy hogyan is megy ez a valójában. Már régóta scrum alapon szeretek dolgozni, de az iterációk tervezése, a különböző gyakorlati módszerek hasznossága vagy haszontalansága, a projekt működtetése, a csapattagok motivációja és irányítása, a vezetési stílusom csiszolgatása – ezek leginkább a tapasztalatból jönnek.
És rettentően élvezem a tanulást.
CeBIT 2011
Múlt héten kollégáinkkal kiállítottunk a CeBIT-en. Érdekes volt kicsit kiszakadni a kód-funkciók-release körből, és más sapkát húzni. Annyira az volt, hogy első nap még le se esett, milyen fárasztó is ez. Pedig olyan egyszerűnek tűnik – megszólítjuk a járókelőt, ő érdeklődni fog, beülünk, elmutogatjuk neki a rendszert, válaszolunk a kérdéseire, adunk neki további elérhetőséget.
Ezzel szemben a valóság: ébredés hajnalban, hogy a stand nyitásra kész legyen (és még beférjen egy gyors kávé is). Nap közben ha sok az érdeklődő akkor az irgalmatlan pörgés fáraszt, ha kevés, akkor az unalom csigázza el az embert. Bedobóembernek nem vagyok jó. Videóriport-alanynak sem. Szórólapot osztani mondjuk tudok, és aközben körbe tudtam járni a többi pavilont is. Öt körül már teljesen lemerült zombiként csak az óránkat nézzük: mikor lesz már vége? Hat előtt tíz perccel pakolás kezdete, hátha már nem jönnek, de azért a demógépet szedjük szét utoljára, hatkor repülőrajt, ki az autóhoz. Autópályán dugó.
És ezekkel együtt is hatalmas élmény volt. Látni, hogy másokat tényleg érdekel amit csináltunk, használni akarják, vannak ötleteik is, hogy mit kéne még belerakni. Kiderült, hogy terméket bemutatni angolul is tudok. Láttuk azt is, hogy mások milyen irányba haladnak (a privát felhőről már készül a cikk az Info-Frame blogra, a computer-brain interface-t meg látni kell hogy elhiggye az ember). Sörözni a kollégákkal az esti csülök után, nap közben leadni a drótot hogy a nagy kapkodás mellett hol találunk valami szuvenírnek is alkalmas reklámajándékokat. Beszélgetni a tősgyökeres brit szomszéd kiállítókkal. Érezni, hogy bár kis cég vagyunk, mégis tudtunk valami olyasmit készíteni, ami Európa-szinten is érdekes lehet.
Nagyon jó volt résztvenni benne.
ms projekt
épp projektet tervezek. vagy terveznék, csak a work és duration szívások beszippantottak.
van egy feladat, 8 órát becslek rá. szerintem ez a work. van egy fejlesztő, aki napi 4 órában tud ezzel foglalkozni. tehát ha megkapja a feladatot, két nap alatt fogja megcsinálni. szerintem ez a duration.
namost. ha ezeket megadom a projektnek, azt szépen kezeli is. viszont ha megváltoztatom a worköt (mert változott a becslés, mondjuk 10 óra kell hozzá), akkor a durationt nem számolja újra. mert csak. ha a durationt változtatom, a worköt újraszámolja.
azt ki se mertem próbálni, hogy a projekttag allokációját változtatom 50%-ról 40-re, hogy akkor mit számol újra.
valamit még meg kell tanulnom erről
Agile ALM – Opposites Attract
http://www.cmcrossroads.com/cm-journal-articles/13601-agile-alm-opposites-attract
Újabban azon gondolkodom sokat, hogy hogyan lehet az agilis fejlesztési módszertanokat beilleszteni egy szoftver életciklus módszertanba. Például az agilis módszerek az élőszavas kommunikációt preferálják, de alkalmazás supportot szájhagyományra elég nehéz építeni. Ehhez ad ötleteket a cikk.

Legutóbbi hozzászólások