Posts Tagged ‘architecture’
Kdy databáze nepoužívat naplno
Narazil jsem dnes na článek obsahující pozoruhodný mix nesouvisejících konceptů a zakončený bizarně nekompromisním prohlášením, že:
Dnešní rychlokvašná “MySQL generace” totiž vůbec neví, že databáze jsou určené k tomu, aby se v nich programovalo.
Stručný výtah pro ty, kdo se nechtějí celým pojednáním prokousávat:
- Nadstavby nad API pro komunikaci s databází (neboli autorovo slovníkem “databázové layery”) jsou špatné, pokud podporují více databázových systémů
- Tyto nadstavby mají smysl pro některé open-source projekty, kde je “rychlost nadřazena nad výkon a spolehlivost” (wtf?)
- Autor v TSQL vytvořil backend webu s návštěvností v řádu statisíc pageviews denně, a považuje to za správné
- Výše citované tvrzení o “MySQL generaci” je doplněno úvahou o tom, že nepsat backend webu v SQL dialektu o síle obdobné T-SQL často značí neznalost
Zvážit podporu více databází je pochopitelně namístě, pokud vyvíjíme produkt, který si uživatelé/zákazníci budou instalovat ve svém prostředí. Mimochodem, záhadou zůstává, z jakých důvodů autor původního článku tento smysl přiznává jen open-source projektům.
Více podporovaných databází znamená více potenciálních zákazníků. Jaké procento kódu se vyplatí psát pro každou databázi zvlášť je jistě věcí ekonomické úvahy zohledňující specifika konkrétního produktu. U “běžné databázové aplikace” se ale toto procento dle mého názoru bude blížit nule.
Takové “běžné databázové aplikace” si podle nasazení můžeme zjednodušeně rozdělit do tří skupin:
- Aplikace, která zdaleka nezatíží ani jeden server
- Aplikace, které jeden server zdaleka nestačí
- Aplikace, která perfektně vytíží právě jeden server, plus minus autobus
Co si budem povídat, u skupiny prvni je výkon získaný vykonáváním aplikační logiky v databázi nepodstatný.
U skupiny číslo dvě si uvědomíme, že horizontální škálování v zásadě bezstavové aplikační logiky je brnkačka, a případným zástupcům“rychlokvašné MySQL generaci” jen poděkujeme za prozíravé rozhodnutí do aplikační vrstvy nacpat co nejvíc logiky, kterou by rÁdobyprofesionál programoval v databázi.
Časem podobně jako třeba eBay stejně zjistíme, že na aplikační vrstvu budeme muset převést i operace, které by nás dřív nenapadly – třeba spojování tabulek.
Co se týče skupiny číslo tři, ať každý sám zváží, jak dlouho do ní jeho aplikace bude spadat.
Jak se zbavit HTTP sessions
V příspěvcích o eBay a AppEngine jsem zmiňoval, že používání HTTP sessions nejde úplně dobře dohromady s požadavky na horizontální škálovatelnost.
Používat sessions je lákavé, umožňují programátora odstínit od bezstavovosti HTTP protokolu. Na druhou stranu, jakmile aplikace přeroste možnosti jednoho stroje, tak začnou komplikovat život, když chcete provozovat load balancing přes cluster aplikačních serverů: duplikovat je napříč servery je patrný overhead, sticky sessions neméně zjevně snižují efektivitu load balanceru.
Jinými slovy: odstiňovat programátory od bezstavovosti HTTP vlastně nemusí být až tak dobrý nápad.
Nejmenší zlo je nakonec sessions ukládat do nějakého relativně persistentního úložiště vně aplikačního serveru – zpoždění sítě a potřebné serializace a deserializace sice mírně brzdí, ale aspoň neovlivňují zbytek clusteru.
Tedy, nejmenší zlo za předpokladu, že sessions používáme.
K čemu vůbec sessions?
K čemu se vlastně HTTP sessions používají? Napadá mě:
- udržování identity uživatele + kešování osobních dat
- udržování stavu uživatelského rozhraní (JSF, dívám se vaším směrem…)
- nákupní košík
- kešování informací potřebných pro stránkování dat (opravdu to někdo radí)
- a další – příklady uvítám v komentářích
Pokud mne laskaví čtenáři v komentářích nedoplní něčím nečekaným, dalo by se používání sessions rozdělit do následujících částečně se překrývajících kategorií:
- autentifikace
- kešování
- antipatterny
Antipatterny
Nevýhody používání sessions pro ukládání aktuální pozice při stránkování dat pitvali už před necelými deseti lety členové Usenetové skupiny cz.net.internet (a po nich i před nimi jistě spousta dalších).
Z nějakých záhadných důvodů se jako typický důvod pro sessions uvádí nákupní košík. K tomu mě nenapadá jiný důvod než že jej kdysi kdosi použil v nějakém tutorialu na sessions a od té doby to každý papouškuje: košík by měl být odolný proti výpadku aplikačního serveru, navíc se neaktualizuje ani nezobrazuje tak často, aby musel být nutně kešován – zkrátka i když jeho trvání obvykle nebývá dlouhé, je velmi záhodne jej ukládat do databáze.
Jako antipattern mi osobně přijde i přístup JSF – a to ať už se stav stromu komponent ukládá do session nebo na klientovi. Ale vzhledem k popularitě tohoto frameworku mi asi něco uniká. Doufám.
Kešování
Session může působit dojmem jako bezva struktura pro kešování, aspoň dokud si člověk neuvědomí nevýhody popsané více. A dokud nezačne kešovat data, která mohou být modifikovány v rámci jiných sessions. A když si nevýhody uvědomí, tak nejspíš sáhne po něčem, co bylo pro kešování navrženo a uvedenými nedostatky ve škálovatelnosti netrpí. Třeba memcached. A těch pár zlomků sekundy na zpoždění sítě a (de)serializaci holt obětuje.
Autentifikace
Session se asi nejčastěji používá pro udržování informací o přihlášeném uživateli. Fakticky se ale jedná o speciální případ kešování popsaného níže – pokud víme, že o uživateli potřebujeme znát skutečné jméno, adresu, a základní preference, prostě si je můžeme nasypat do memcached pod těžkouhodnutelným klíčem generovaným podobným mechanismem jako session.
A pokud od autentifikace očekáváme jen ověření identity uživatele, můžeme prostě do cookie nastavit přímo identifikátor uživatele, jen digitálně podepsaný nebo ještě lépe zašifrovaný. Pokud autentifikační služba není izolována na vlastním clusteru, symetrické šifrování by mělo bohatě postačí. Na druhou stranu se v tomto případě se musíme postarat o pár praktických záležitostí okolo správy klíčů a deploymentu.
Obrázek: Možnosti ověření a interpretace authentication tokenu – kešování a kryptografie
Kryptohrátky jsou zbytečným overheadem v tradični aplikaci, kdy většina požadavků je zasílána za účelem vykreslení celé stránky – typicky vždy budete muset znovu zobrazit jméno uživatele a podobně, tudíž si hrábnutí do cache neušetříte.
Naopak pokud si mantru “udržovat stavu na klientovi” vykládáte po vzoru GMailu tak, že webová aplikace se sestává z pár HTML stránek, kterou uživatel porůznu aktualizuje AJAXem, pak samozřejmě může kryptografické ověřování a interpretace session tokenu přispět ještě o trošku k lepší odezvě a škálovatelnosti.
Pokud někomu ze čtenářů zbudou síly něco napsat, zajímalo by mě:
- k čemu výše neuvedenému používáte sessions?
- zkoušeli jste v praxi vytvořit bez použití sessions netriviální víceuživatelskou webovou aplikaci?
- a pro znalce a fanoušky Java Server Faces – máte po přečtení výše uvedeného dojem, že mi ohledně této technologie něco zásadního uniká?
Odkazy
- Gojko Adzic: Put the webserver on diet to increase scalability
- Cal Henderson: Scalable web architectures: Common patterns & approaches
eBay, Java a škálovatelnost
Jak to vypadá, když se za pomocí J2EE vytváří webová aplikace, jejíž databáze obsahuje přes dva petabajty dat (peta = 10245) a jejíž dvě stě milionů registrovaných uživatelů jejím prostřednictvím v kterýkoli čas nabízí okolo sta miliónů položek?
Architektura eBay
- na nejhrubší úrovni rozděleno na databázovou vrstvu, aplikační vstvu, vyhledávací systém a operations
- Aplikační vrstva:
- nedrží stav (tedy žádné sessions, natož stateful session beans)
- schválně jsem se podíval na HTTP hlavičky, zaujala mě cookie jménem “nonsession”
- schválně jsem se podíval na HTTP hlavičky, zaujala mě cookie jménem “nonsession”
- asi 100 funkčních celků, v terminologii eBay “apps” (někdo by možná řekl “business services”), dohromady to dělá cca 15,000 serverů
- aplikační servery spolu nekomunikují, běží nezávisle na sobě (což lze snadno díky předchozímu bodu)
- nedrží stav (tedy žádné sessions, natož stateful session beans)
- Databázová vrstva:
- rozdělena vertikálně na něco přes 70 funkčních celků (databází). Ty jsou dále řezány horizontálně podle hlavního klíče pro daný logický celek
- většina náročných obvykle databázových operací se provádí na aplikační vrstvě; zmiňují se joiny, kontrola referenční integrity, třídění. Nepěstují se žádné uložené procedury (sem tam nějaký jednoduchý trigger)
- eBay nepoužívá transakce (tedy kromě PayPalu, který pod eBay taky patří)
- v praxi to znamená, že je vymezena skupina životně důležitých dat, které musí být vždy v konzistentním stavu, u ostatních se garantuje pouze “best effort”
Kdy se hodí Java?
Zajímavé jsou použité technologie: J2EE (konkrétně WebSphere) a Oracle, čímž se eBay výraně odlišuje od různých Flickrů a podobné havěti. Co mají ale tyto weby s eBay společné, jsou architektonické patterny, které se na hony vzdalují představě správné J2EE aplikace z dob EJB2.0. Ale na tom samozřejmě není nic divného.
Proč tedy v eBay Javu vůbec používají?
Dan Pritchett ve své prezentaci z roku 2006 píše: “[we] rewrote the entire application in J2EE … which gave us chance to architect the code for reuse and separation of duties”. A co si tak vzpomínám, to byl možná hlavní důvod, proč jsem se kdysi dávno po nějakých pěti letech s Perlem a PHP pouštěl do psaní webových aplikací v Javě.
Odkazy
