Blog | Jak psát škálovatelné aplikace

Jak psát škálovatelné aplikace

Když roste zátěž, nezbývá, než na situaci reagovat a škálovat. S tím přichází řada potenciálních chyb a problémů. Tady najdete seznam myšlenek, které vám usnadní škálování aplikací.

Horizontální vs vertikální škálování

Horizontální škálování je synonymem přidávání dalších serverů. Vertikální škálování je zvyšování výkonnosti serveru. Dokud můžete, dejte přednost vertikálnímu škálování před horizontálním. Neuvěříte, o kolik jednodušší život mají ti, komu stačí 1 databázový server oproti těm, kteří jich musí mít řadu.

Jak na to?

Kromě kupování více RAM a silnějšího procesoru, SSD disků (vše z toho pravděpodobně chcete dělat a měli byte), je tu ještě jedna možnost.

Použijte další – mnohem rychlejší – programovací jazyk. Pokud používáte PHP nebo Ruby, zkuste dát šanci JVM, Pythonu, jazyku překládanému do C. Vhodný programovací jazyk vám dá mnohdy 30–300 násobný růst výkonu. Ať už to je Java, C#, JS/node.js, jedná se o jazyky, které umí kdekdo. Nebo se může jednat o jazyky typu Python, Clojure, Haskell, F#, které jsou krásné a také velmi výkonné.

Použijte ještě jeden jazyk. Stojí to za to. V okamžiku, kdy se vám podaří třeba zestonásobit výkon, může se stát, že váš limit se posune tolik, že na 1 serveru utáhnete celou svou potenciální cílovku (nepodceňujte výkon dnešních počítačů).

Ze zkušenosti během dvou, tří měsíců zvládnou být vývojáří produktivní i v dalším jazyce (který je velmi odlišný od toho, který lidé umí) a těžit z vysokého výkonu.

Já k PHP přidal Clojure. Nejenže je mnohem rychlejší, produktivita je vysoká, ale nemusím se bát napsat službu, která poběží bez restartu celé měsíce. JVM je velmi stabilní.

Do horizontálního škálování jděte až tehdy, kdy jste vyladili výkon na 1 serveru tolik, že není pořádně kam růst.

Kešujte jako diví

Nejlepší škálování je takové, které se děje nezbytně málo. Další z věci, kterou zvažte, je cache.

  • nasaďte memcache na key-value kešování
  • na složitější potřeby využijte redis, zejména tam, kde potřebujete atomickou multioperaci
  • nasaďte varnish jako reverzní proxy
  • měřte, že hit rate je přes 90 %, jinak kešování v daném místě odstraňte
  • zvažte strategii pro invalidaci, jakmile je cache plná, hledejte algoritmus, díky kterému relevantní informace zůstanou v cache co nejdéle

Prakticky každý, kdo to s výkonností a škálovatelností myslí vážně, ten kešuje. I dobře udělaná cache může výrazně oddálit okamžik, kdy budete muset výrazněji horizontálně škálovat.

Command Query Responsibility Segregation

V okamžiku, kdy už potřebujete více databází, použijte Command Query Responsibility Segregation.

Zní to složitě, ale v podstatě je to o tom, že v modelech nemáte jen 1 adaptér, ale máte dva. Jeden ukazuje na master, druhý na slave. Master používáte na zápis, slave na čtení. Těch slave serverů může být víc.

Toto vás zase na nějakou dobu posune. Pokud použijete vše, co jsem zatím zmínil, budete v ČR výjimkou, pokud vám tyto 3 věci nebudou stačit.

Použijte provisioning

Když aplikace roste, začnete řešit problém, jak nahrávat kód na více serverů najednou. Většina správců serverů používají naivní řešení postavená na shellscriptech. Každá firma je jiná, většinou nemá moc dobré logování, štábní kulturu, neverzuje infrastrukturu, nemůže se vrátit zpět.

Já doporučuji použít Ansible nebo Salt Stack (osobně preferuji Ansible, ale obojí je použitelné). Velkou výhodou je to, že ona řešení jsou proti shellscriptům deklarativní. Pokud pustím stejný konfigurační soubor víckrát, nic se nestane. Ansible najde jen rozdíl proti stávajícímu stavu a udělá nezbytnou změnu.

Ve spojením s Vagrantem a Dockerem můžou u sebe i členové týmu provozovat kopii infrastruktury, což nejenže šetří čas a zvedá produktivitu, ale i brání chybám.

Configuration management

Jedna z výhod Ansible je i v tom, že se nehodí jen na provisioning, ale i na configuration management, kdy máte standardizovanou cestu, jak udržovat informace specifická pro různá prostředí bez toho, abyste museli psát nějaké své skripty, které budou doplňovat hodnoty.

S růstem počtu serverů, ale i s růstem počtu lidí v týmu, roste důležitost managovat konfiguraci. Použijte Ansible a máte o starost méně.

Jako FS použijte CDN nebo Riak

Riak není moc dobrý jako databáze. Přinejmenším nepatří k rychlíkům, jako je Mongo nebo Couch. V čem je ale docela slušný, je náhrada filesystému, který je distribuovaný.

Takže pokud nechcete použít nějakou existující CDN (což je snadné a vhodné řešení na statické soubory, po zašifrování i na zálohy), můžete na toto použít Riak.

Správci serverů ho milují, je jednoduché ho nasadit, jen pustíte proces, napíšete příkaz, který uzel přidá do ringu a máte hotovo.

Pište mikroslužby

Přemýšlím, zda neopustit toto slovo, za dobrou myšlenkou se skrývá až moc buzzwordování. V poslední době pomáhám několika firmám zvedat výkon. Vše je mnohem snažší, když můžete výpočetně náročný kousek vzít, izolovat, přepsat do jazyka rychlého jako C, umístit ho třeba i na samostatný server, schovat ho za frontu, udělat s ním kouzla, která by jinak nešla, kdyby tahle část aplikace byla jen kousek monolitu.

Naučte se napsat malou aplikaci, zapojit ji do monitoringu, sledovat výkon, zdraví služby. Naučte se psát rychlá API. K mikroslužbám dospějete sami.

Používejte fronty

Nejčastěji radím RabbitMQ, pokud je potřeba, aby úlohy ve frontě přežily pád, ZeroMQ, pokud to není nezbytně nutné, ale je nezbytná maximální rychlost. Možností je víc, Kafka, ActiveMQ atd.

Používejte fronty. Pokud programujete v PHP, použijte fronty dvojnásob, dají vám paralelismus pro chudé zalevno.

Používejte fronty, můžete jimi propojit jednotlivé prog.jazyky, snáze se monitorují, než jen volání API.

Používejte fronty, když naroste zátěž, služba poběží na 100 % výkonu a když zátěž poleví, fronta doběhne. Váš server nespadne, pojede dál.

Když už máte opravdu hodně dat

Jak vám budou narůstat data, zvažte partitioning, tedy fyzické rozdělení dat na více serverů. Dobře zvažte klíč, podle kterého k rozdělení dojde. Špatně udělaný partitioning pošle všechny dotazy na 1 server a nepomůže vám – spíš to ten server upeče.

Od určité meze (říkejme jí třeba „opravdu hodně“) už nemají přesné hodnoty velký smysl vypočítávat z reálných záznamů. Agregujte informace z větších celků do menších.

Další možností je vytvoření si vlastního „datového skladu“, kam budete odlévat data a který bude mít vše od počátku věků. Na produkci data zagregujete a pravidelně je smažete a budete udržovat jen mnohem kratší interval (záleží na okolnostech, ale 18 měsíců je často až až).

Upload souboru ve 2 krocích

Jedna ze začátečnických chyb, které se lidé dopouštějí při běhu na více serverech, je to, že zapomínají, že upload souboru přijde na jeden z výkonných serverů, ale než je soubor k dispozici, je potřeba ho umístit i do CDN.

Tzn. místo procesu: nahrál se mi soubor → do db poznačím, že soubor mám, bude proces: nahrál se mi soubor → do db poznačím, že soubor nahrávám → soubor nahraju do CDN → do db poznačím, že soubor mám.

Pozor, upload souboru může být skrytý, např. začnete nahrávat článek do CMS v cloudu, to se odkazuje na soubory, které nahrává uploader. Článek můžete zveřejnit až poté, co je nahrán poslední soubor.

Sessions v memcache nebo db

Neudržujte sessions na výkonném stroji (v Apache apod.). Dokud vystačíte s 1 memcache na sessions, mějte tyto v memcache. Až to nepůjde, přesuňte je do databáze.

Sessions na výkonném stroji patří k dalším začátečnickým chybám při budování služby, která má běžet na více strojích.

Zjednodušujte db

Při rozdělování db na více serverů, se může snadno část (zažil jsem to), že některé tabulky se vymezí do samostatné db, která se poté posune na další server. Jakmile bude hrozit něco takového, radši udělejte 2 samostatné SQL dotazy, než abyste napsali delší join.

Mnohdy je takové řešení rychlejší, než složitý SQL dotaz.

Škálujte i betu

Pokud běžíte na více serverech, mějte i beta verzi aplikace na více serverech. Některé chyby se na jednoserverové konfiguraci neprojevují, to až když běží víc služeb naráz. Vždy se před releasem na produkci ujistěte, jak se aplikace chová na více instancích beta serveru.

Odstraňujte Single Point of Failure

Jak vám poroste zátěž, budete mít víc a víc serverů. Čím více serverů, tím vyšší šance, že se něco pokazí. Když se něco pokazí u služby, která běží na 20 serverech, nemělo by to znamenat výpadek služby.

Tento bod jsem si nechal na konec. Když budete provozovat jeden, dva servery, nemá něco takového smysl. Na velkých instalacích je ona blbuvzdornost jeden z podstatných aspektů. Jedna ze služeb, která nemá Single Point of Failure, je Riak, dál pak broker-less služby, např. Ansible, poslouží dobře.

Závěrem

Než začnete cokoliv měnit, monitorujte všechno, databáze, síťovku, disky, CPU. Když změna nepomůže, vraťte ji zpět. Hledejte čísla, která vám pomůžou.

Agile

Předejte zkušenosti i dalším a sdílejte tento článek!

Předchozí článek
Následující článek


Jiří Knesl
Business & IT konzultant

Jiří Knesl poprvé začal programovat v roce 1993. Od té doby, díky skvělým učitelům a později zákazníkům, měl možnost neustále růst v oboru vývoje webových aplikací a informačních systémů. v roce 2002 se přidal zájem o ekonomii a v roce 2006 o organizaci práce. Vším tím se konstantně profesně zabývá jak ve svém podnikání, tak i u zákazníků. Za posledních 5 let vydal na tato témata přes 400 článků.

Prohlédněte si moje reference

Mám zkušenosti z rozsáhlých projektů pro korporace, velké podniky, střední i malé firmy, ale i pro startupy v cloudu. Zvyšoval jsem jejich know-how, pomáhal nastavovat jejich organizační strukturu, byl lektorem a mentorem v náročných situacích. Podívejte se, jak vidí můj přínos samotní klienti.

Sledujte mé postřehy na sociálních sítích