Masarykova univerzita Fakulta}w¡¢£¤¥¦§¨  informatiky !"#$%&'()+,-./012345

Rozšíření Ruby cartridge pro platformu OpenShift

Bakalářská práce

Petr Brázdil

Brno, 2013 Prohlášení

Prohlašuji, že tato bakalářská práce je mým původním autorským dí- lem, které jsem vypracoval samostatně. Všechny zdroje, prameny a lite- raturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj.

Vedoucí práce: RNDr. Petr Švenda, Ph.D.

ii Poděkování

Chtěl bych poděkovat zaměstnancům firmy Red Hat pracujících na pro- jektu OpenShift za odborné rady a připomínky, zejména mé díky patří Michalu Fojtíkovi, který mě byl vždy schopen nasměrovat správným směrem. Také bych chtěl poděkovat vedoucímu této práce, RNDr. Pe- tru Švendovi, Ph.D., za pomoc a cenné rady. Mé poděkování také patří rodině a přátelům, za jejich podporu a trpělivost.

iii Shrnutí

Práce se zaměřuje na platformu OpenShift, kterou zasazuje v rámci Cloud computingu do jeho kontextu a následně popisuje její nejdůleži- tější aspekty. Věnuje se implementacím Ruby a webovým serverům pro webové aplikace psané v Ruby. Jako součást práce bylo vytvořeno roz- šíření Ruby cartridge umožňující zvolení použitého webového serveru a obsahující podporu pro implementaci JRuby. Toto rozšíření je spolu s vytvořenou testovací aplikací použito pro srovnání výkonu webových serverů na platformě OpenShift Online.

iv Klíčová slova

OpenShift, Advanced Ruby cartridge, webový server, implementace Ruby, JRuby, , WebSockets

v Obsah

1 Úvod ...... 3 2 Cloud computing ...... 5 2.1 Infrastruktura jako služba ...... 5 2.2 Platforma jako služba ...... 6 2.2.1 Heroku ...... 6 2.2.2 CloudFoundry ...... 7 2.2.3 OpenShift ...... 7 2.3 Software jako služba ...... 7 3 OpenShift ...... 8 3.1 Architektura ...... 9 3.2 Škálování aplikací ...... 10 3.3 Použitý způsob virtualizace ...... 11 3.4 Proces nahrání webové aplikace ...... 11 3.5 Varianty platformy OpenShift ...... 12 3.5.1 OpenShift Origin ...... 12 3.5.2 OpenShift Online ...... 13 3.5.3 OpenShift Enterprise ...... 13 4 Webové aplikace psané v Ruby ...... 14 4.1 Webové frameworky ...... 14 4.1.1 Ruby on Rails ...... 15 4.1.2 ...... 15 4.2 Implementace jazyka Ruby ...... 15 4.2.1 Ruby MRI a Ruby YARV ...... 16 4.2.2 JRuby ...... 17 4.2.3 ...... 17 4.3 Webové servery ...... 18 4.3.1 Thin ...... 18 4.3.2 Puma ...... 19 4.3.3 Unicorn ...... 19 4.3.4 Passenger ...... 19

1 4.4 Podpora webových aplikací v Ruby u platforem ..... 20 5 Advanced Ruby catridge ...... 21 5.1 Struktura cartridge ...... 22 5.2 Volba webového serveru a implementace Ruby ...... 22 5.3 WebSockets ...... 23 5.4 Podporované implementace Ruby ...... 24 5.5 Podporované webové servery ...... 25 6 Srovnávací výkonnostní testy ...... 27 6.1 Testovací webová aplikace ...... 27 6.2 Testovací metodika ...... 28 6.3 Použitá konfigurace webových serverů ...... 29 6.4 Výsledky výkonnostního srovnání ...... 30 6.4.1 Výsledky při vypnutém škálování ...... 31 6.4.2 Výsledky při zapnutém škálování na 5 gearů . . . 32 6.4.3 Výsledky při zapnutém škálování na 10 gearů . . 33 7 Závěr ...... 34

2 Kapitola 1 Úvod

Dříve bylo zcela běžné využívat webové hostingy pro nahrání webo- vých aplikací na internet. Webové hostingy poskytují sdílené hardwa- rové zdroje a minimální možnosti úprav konfigurace použitého běho- vého prostředí, na kterém webová aplikace běží. Disponují omezenou podporou pro programovací jazyky, nejčastěji se setkáváme s podporou pro programovací jazyk PHP, který je pro webové hostingy atraktivní zejména díky jeho jednoduché serverové konfiguraci a zároveň i popu- laritě mezi webovými vývojáři. S příchodem Cloud computingu začaly vznikat platformy usnadňu- jící provoz a nahrávání webových aplikací na internet. Mají podporu pro mnoho programovacích jazyků, včetně Ruby, Python, PHP, Java nebo třeba Node.js. Tyto platformy dokáží reflektovat aktuální potřeby po hardwarových zdrojích díky možnosti škálování a zároveň umožňují konfigurovatelnost běhového prostředí. Právě jednou z takových plat- forem je platforma OpenShift. Cílem této bakalářské práce je vytvořit rozšíření Ruby cartridge pro platformu OpenShift navíc podporující implementaci Ruby, která běží nad Java Virtual Machine (JVM), zvanou JRuby, a umožňující správu použitého webového serveru. Poté toto rozšíření Ruby cartridge využít spolu s vytvořenou testovací aplikací ve frameworku Ruby on Rails pro výkonnostní srovnání webových serverů, jež vytvořená cartridge implementuje. Naměřené výsledky poté vhodně reprezentovat. V druhé kapitole této práce definuji pojem Cloud computing a za- řazuji platformu OpenShift do jeho kontextu. V další kapitole se věnuji popisu platformy OpenShift, zejména aspektům, které jsou nutné k po- chopení této práce. Čtvrtá kapitola obsahuje stručný úvod do webo- vých aplikací psaných v Ruby. V páté kapitole se věnuji vytvořenému rozšíření Ruby cartridge. V poslední kapitole reprezentuji naměřené vý-

3 1. Úvod sledky výkonu webových serverů pomocí grafů, které se snažím vhodně interpretovat.

4 Kapitola 2 Cloud computing

Každým dnem se počet aktivních uživatelů internetu navyšuje, náklady na zázemí jednotlivých služeb rostou. Vzniká potřeba maximalizovat efektivitu hardwarových zdrojů a snížit celkové náklady na provoz. Na scénu přichází pojem Cloud computing, někdy také označován jako Cloud. Pojem Cloud computing se již pokoušelo definovat mnoho od- borníků, jednotlivé definice se mohou v mnoha případech rozcházet. V této práci se budu opírat o definici uvedenou v dokumentu The NIST Definition of Cloud Computing [1], který byl publikován Národním in- stitutem pro standardy a technologie působícího v USA. Právě tento dokument je často citován odbornou literaturou. Cloud computing je zde definován jako model pro umožnění všu- dypřítomného, spolehlivého a on-demand (na požádání) síťového pří- stupu ke sdílené nabídce konfigurovatelných výpočetních zdrojů (napří- klad sítí, serverů, uložišť, aplikací a služeb), které mohou být poskyt- nuty v krátkém čase a spuštěny s minimálním vynaloženým úsilím. Dokument mimo jiné definuje tři modely poskytovaných služeb, In- frastruktura jako služba, Platforma jako služba a Software jako služba.

2.1 Infrastruktura jako služba

Infrastruktura jako služba nabízí výpočetní zdroje (virtuální servery, úložiště a sítě), které je zákazník schopen využít pro potřeby libovol- ného softwaru, včetně operačního systému a jiných aplikací. Zákazník má přístup ke konfiguraci operačního systému, úložišť a jiných použi- tých aplikací. Nemá však kontrolu nad hardwarovými zdroji pohánějí- cími tento model. Mezi hlavní výhody tohoto řešení patří zejména přenesení odpověd- nosti za provoz na dodavatele a rychlost adaptace na potřeby zákaz-

5 2. Cloud computing níka. Na druhou stranu, uchovávání citlivých dat u poskytovatele nebo nemožnost naprosté kontroly nad použitým hardwarem hodně firem odradí [2]. Největším poskytovatelem služeb tohoto typu je firma Amazon [3]. Amazon Elastic Compute Cloud1, někdy také označována jako Ama- zon EC2, je služba poskytující virtuální servery. Tuto službu využívá například platforma OpenShift Online nebo platforma Heroku.

2.2 Platforma jako služba

Platforma jako služba poskytuje zákazníkovi možnost nahrát vytvořené webové aplikace na internet. Webové aplikace musí být vytvořeny po- mocí programovacích jazyků, knihoven a nástrojů podporovaných po- skytovatelem. Níže se věnuji stručnému popisu platforem s podporou pro webové aplikace psané v Ruby, Heroku, CloudFoundry a OpenShift. Srovnání z hlediska podpory pro webové aplikace v Ruby se věnuji v sekci 4.4 Pod- pora webových aplikací v Ruby u platforem.

2.2.1 Heroku

Platforma Heroku2 vznikla v roce 2007, v roce 2010 byla koupena fir- mou Salesforce.com. V začátcích platforma Heroku disponovala pod- porou pouze pro Ruby aplikace, v současné době však podporuje ce- lou řadu jazyků, včetně Ruby, Java, Node.js, Python, Clojure, PHP a Scala. Platforma Heroku nabízí jednoduché webové rozhraní pro správu webových aplikací a přehledný model placení. Platforma Heroku je kon- kurencí zejména pro platformu OpenShift Online3. Aplikace nahrané na platformě Heroku mohou využívat přídavných externích služeb. Vybírat můžeme z mnoha monitorovacích služeb, da- tových úložišť nebo také vyhledávacích nástrojů.

1. 2. 3. OpenShift Online se věnuji v podsekci 3.5.2 OpenShift Online.

6 2. Cloud computing 2.2.2 CloudFoundry Platforma CloudFoundry4 byla vytvořena firmou VMWare, první verze byla vydána v roce 2011. Disponuje podporou pro jazyky Java, Ruby, Node.js a Scala. Zdrojové kódy jsou dostupné pod licencí Apache Li- cense 2.0. OpenShift Origin5 je konkurencí pro platformu CloudFoun- dry.

2.2.3 OpenShift OpenShift6 je platforma pro nahrávání webových aplikací na internet od společnosti Red Hat. Prvotní verze se objevila v roce 2011. Podporuje programovací jazyky Java, Ruby, PHP, Python, Perl a Node.js. V následující kapitole se věnuji bližšímu popisu platformy Open- Shift.

2.3 Software jako služba

Zatímco Platforma jako služba nabízí prostředky pro běh webových aplikací, Software jako služba poskytuje samotnou webovou aplikaci, připravenou pro využití koncovým zákazníkem. Webová aplikace je pří- stupná pomocí webového prohlížeče nebo klientské aplikace. Velkým poskytovatelem služeb tohoto typu je firma Google, nabízející služby jako emailový klient Gmail, kancelářský software Google Docs nebo třeba souborové úložiště Google Disk.

4. 5. OpenShift Origin se věnuji v podsekci 3.5.1 OpenShift Origin. 6.

7 Kapitola 3 OpenShift

OpenShift podporuje několik způsobů komunikace s jeho rozhraním. Prvním je přístup přes klienta rhc, ten je spouštěn v terminálu. Dalším způsobem je webové rozhraní, nenabízí sice tolik možností co první va- rianta, avšak jedná se o jednodušší způsob ke komunikaci s platformou OpenShift. Posledním způsobem je Application Programming Interface (API) nabízející veškerou funkcionalitu předchozích dvou způsobů. Při vytvoření aplikace se automaticky vytvoří takzvaný gear, na který je celá aplikace nahrána. Gear si můžeme představit jako jednu instanci virtuálního serveru obsluhující webovou aplikaci. Každý gear má předem definované parametry, zejména se jedná o limitaci využité operační paměti, úložného prostoru nebo také maximálního počtu sou- borů. Webová aplikace běžící na daném gearu nemůže překročit žádné hodnoty, které jsou pro daný gear nastaveny. Cartridge se používají k přidání podpory programovacího jazyka nebo služby používané webovou aplikací. Jsou instalovány na gear, po- případě geary. Obecně se dají rozdělit na dva typy. Na cartridge, které mohou fungovat samostatně, někdy označované jako primární, a na cartridge zpřístupňující pouze určitou službu, třeba databázi. Primární cartridge jsou například PHP cartridge, Ruby cartridge nebo třeba Py- thon cartridge. Primární cartridge musí být na gear nainstalovány jako první a také právě jednou. Slouží jako stavební kámen pro cartridge zpřístupňující pouze určitou službu. Pokud máme například webovou aplikaci psanou v Ruby využívající databázi MySQL, nejprve přidáme Ruby cartridge a následně cartridge pro MySQL databázi. Cartridge jsou složeny z kontrolních skriptů, ty jsou spuštěny při událostech jako je například instalace cartridge či nahrání nové verze webové aplikace. Každá cartridge přidává v rámci gearu několik glo- bálních proměnných, které jsou k dispozici i pro webovou aplikaci. Pro

8 3. OpenShift webové aplikace jsou užitečné zejména v případě databází, kdy údaje pro připojení k databázi mohou být nastaveny právě užitím těchto pro- měnných. Platforma OpenShift nabízí podporu i pro cartridge vytvořené ko- munitou. Právě díky nim je možné na platformě OpenShift přidat pod- poru pro jazyky a služby, které oficiální cartridge nepodporují. Aby mohla být komunitní cartridge na gear nainstalována, musí být do- stupná ve veřejně přístupném Git repozitáři.

3.1 Architektura

Architektura platformy OpenShift je tvořena zejména dvěma kompo- nentami, Broker a Node. Komunikace mezi nimi probíhá prostřednic- tvím zpráv ukládaných do fronty implementované pomocí ActiveMQ1. Komponenta Broker se stará o správu webových aplikací a uživa- telských účtů. Tato komponenta nabízí API využívající architektury REST2. Toto rozhraní je využíváno webovou administrací platformy OpenShiftu a klientem rhc. Využít ho můžeme i ve vlastních externích aplikacích. Komponenta Node je využívána pro ukládání jednotlivých gearů. Požadavky na správu gearu zasílá vždy Broker. Na této komponentě jsou přidány všechny programovací jazyky a služby, které oficiální car- tridge podporují [4]. Webová aplikace využívající více gearů může mít jednotlivé geary uloženy na různých komponentách Node. Komunikace mezi nimi pak probíhá přes speciální porty, které jsou přístupné díky HAProxy3. OpenShift podporuje zapojení mnoha topologií. Pro testování je vhodná topologie, kde veškeré komponenty jsou na jednom stroji. U pro- dukčního prostředí je častá topologie, kde figuruje komponenta Broker společně s frontou zpráv na jednom stroji. Další stroje jsou nastaveny jako komponenty Node, těch může být několik a jejich počet může být v budoucnu měněn dle potřeb.

1. 2. 3.

9 3. OpenShift 3.2 Škálování aplikací

Webové aplikace obsluhující velké množství požadavků typicky využí- vají škálování, v případě platformy OpenShift je použito horizontální škálování4. V současné době je škálování řešeno použitím HAProxy. HA- Proxy se stará o vyvažování zátěže mezi geary. Pokud HAProxy zazna- mená velký počet příchozích požadavků na webovou aplikaci, zašle po- žadavek pro přidání nového gearu. Komponenta Node naalokuje místo pro nový gear, nainstaluje primární cartridge a nahraje kopii zdrojo- vých kódů webové aplikace. Jakmile je tento gear připraven, HAProxy na něj začne přeposílat požadavky ke zpracování. Naopak při poklesu počtu požadavků zašle HAProxy požadavek na vypnutí nepotřebných gearů. Primárním gearem je označován gear, který vznikne jako první, tedy při přidání webové aplikace. U škálovatelné aplikace obsahuje primární gear jak HAProxy, tak i webovou aplikaci. Jakmile počet gearů do- sáhne většího počtu než tří, pak se webová aplikace na primárním gearu vypne, aby uvolnila HAProxy více hardwarových zdrojů. Jinak by se z primárního gearu mohlo stát úzké hrdlo, které by celý proces škálování znemožnilo. Na stránkách platformy OpenShift je uvedeno, že na každý gear je alokováno 16 souběžných požadavků. Pokud systém zaznamená, že alespoň 90% této kapacity je využito, pak zašle požadavek na přidání nového gearu [5]. Dle mého testování toto tvrzení není platné. Nasimu- loval jsem 30 souběžných požadavků po dobu 60 minut na nenáročnou aplikaci5, výsledek byl takový, že žádný nový gear nebyl alokován. Po- kud jsem stejný test provedl na aplikaci značně hardwarově náročnější6, pak nový gear vytvořen byl. Ačkoli tento výsledek se může zdát logický, odporuje tvrzení uvedenému na stránkách platformy OpenShift. V do- stupných materiálech jsem nenašel mnoho dalších informací ohledně této problematiky. Jistě by nebylo na škodu tuto část platformy Open- Shift více zdokumentovat.

4. Horizontální škálování (scale out) znamená přidání nových hardwarových zdrojů pro obsluhu webové aplikace. V kontextu platformy OpenShift se jedná o přidání dalších gearů pro obsluhu webové aplikace. 5. Ruby aplikace, složena pouze ze souboru config.ru, který pomocí rozhraní Rack vypsal jednoduchou HTML stránku. 6. Webová aplikace psaná v Ruby on Rails využívající databázi MySQL.

10 3. OpenShift Škálování podporují až na pár výjimek všechny primární cartridge a jde nastavit jak manuálně, tak i automaticky. Automatické škálování je nastaveno jako výchozí při vytvoření nové škálovatelné aplikace.

3.3 Použitý způsob virtualizace

Platforma OpenShift využívá virtualizace na úrovni operačního sys- tému, nejedná se o virtualizaci na úrovni hypervizoru7 jak by se mohlo na první pohled zdát. Jinými slovy, jednotlivé geary se nenachází v sa- mostatných virtuálních strojích, ale v tomto případě fungují jako běžní Linux uživatelé. Jsou navzájem zapouzdřeni použitím technologií SELi- nux8 a Multiple Categories Security9. Pro limitaci zdrojů přiřazených ke gearu se využívá control groups10 (cgroups), jedná se zejména o limitaci využití procesoru, operační paměti a počtu vstupně výstupních operací. Výsledkem jsou geary fungující jako jednotlivé virtuální jednotky. Neví nic o ostatních aplikacích, potažmo o dalších gearech.

3.4 Proces nahrání webové aplikace

Platforma OpenShift používá pro nahrání webové aplikace verzovací systém Git. Po přidání nové aplikace do platformy OpenShift, do- staneme adresu na Git repozitář nacházející se na primárním gearu. Po provedení příkazu git push započne proces nahrání webové apli- kace, ten se dělí do několika fází. Platforma OpenShift se postará o zastavení a spuštění webové aplikace, další provedené kroky se pro- vádí v závislosti na tom, jaká primární cartridge je použita. Pokud webová aplikace má nějaké specifické požadavky na provedení během tohoto procesu, můžeme přidat action hooks [6]. Deklarují se v adre- sáři .openshift/action_hooks/, jenž se nachází v kořenovém adresáři nahrávané webové aplikace. V první fázi procesu se připraví zdrojové kódy spuštěním akce build. V případě Ruby cartridge se u webové aplikace psané ve frameworku Ruby on Rails jedná o stažení všech potřebných závislostí příkazem

7. 8. 9. 10.

11 3. OpenShift bundle install —deployment. Na konci této fáze je vytvořen artefakt webové aplikace s unikátním identifikátorem vypočítaným jako SHA-1 hash sumy obsahu webové aplikace. V dalším kroku je tento artefakt distribuován i do dalších gearů určených k obsluhování požadavků na webovou aplikaci. Na nich je poté spuštěna fáze activation, po které následuje samotné spuštění webové aplikace. Předešlé artefakty jsou na gearu ukládány, proto v případě výskytu problému je možné se k nim zpětně vrátit. Ve výchozím stavu je ulo- žen pouze jeden starší artefakt. Počet ukládaných předešlých artefaktů je vhodné zvolit v závislosti na zbývajícím volném místě na gearu, je- likož dle mého testování se všechny uložené artefakty započítávají do celkového využitého místa na gearu. Standardně je během celého procesu webová aplikace nepřístupná. Pokud je však webová aplikace nastavena jako škálovatelná a má k dis- pozici více než jeden gear, pak se OpenShift zajistí, aby webová apli- kace byla dostupná během celého procesu nahrání webové aplikace. Je toho docíleno použitím jedné ze dvou technik. První zvaná in-place spustí celý proces přípravy na všech aktivních gearech v dočasné lokaci, poté zastaví gear, nahradí starý artefakt novým a spustí gear. Druhá technika, scale-replace, vytvoří nové geary a na nich spustí celý proces s novou verzí webové aplikace. Mezitím staré geary obsluhují nadále požadavky, které jsou posílány na starou verzi webové aplikace. Během tohoto procesu se staré geary postupně vypínají, tak, aby po dokončení celého procesu geary s novou verzí plynule nahradily geary se starou verzí webové aplikace.

3.5 Varianty platformy OpenShift

Platforma OpenShift je k dispozici ve třech variantách, OpenShift Ori- gin, OpenShift Online a OpenShift Enterprise.

3.5.1 OpenShift Origin Jedná se o open source variantu, která je ke stažení pod licencí Apache License 2.0. Zdrojové kódy jsou k dispozici ve veřejném Git repozitáři11 vedeném u služby GitHub.

11.

12 3. OpenShift V této variantě se promítají veškeré změny a nové funkce jako první. Pro využití této varianty je potřeba disponovat hardwarovým zázemím, na kterém chceme OpenShift Origin provozovat. Nedávné vydání ná- stroje oo-install 12 celý proces instalace zjednodušilo.

3.5.2 OpenShift Online Tato varianta platformy OpenShift je vhodná zejména pro seznámení s platformou a pro provoz běžně náročných aplikací. Hardwarové zázemí není potřeba, OpenShift Online běží na virtuálních strojích poskytova- ných službou Amazon EC2 [7]. K dispozici jsou 3 typy gearů lišící se zejména velikostí operační pa- měti. Limit využití procesoru se dle mého testování u OpenShift Online nemění. Vlastnosti gearů jsou popsány v následující tabulce:

Malý gear Střední gear Velký gear Operační paměť 512 MB 1 GB 2 GB Úložný prostor 1 GB 1 GB 1 GB Vhodné pro PHP, Ruby, Python Java Java

3.5.3 OpenShift Enterprise V dnešní ekonomické situaci se snaží mnoho firem nalézt řešení, jak udělat více za méně vynaložených prostředků. Potřebují rychlým tem- pem nasazovat nové služby, u kterých věří, že v budoucnu se budou podílet na zvýšení firemního zisku. Právě tyto firemní poptávky tlačí na informační technologie, aby byly schopné nabídnout řešení, které se přizpůsobí jejich potřebám, ať už se jedná o hardwarově náročné služby nebo jednoduché aplikace. Právě vyřešit tyto problémy si klade za cíl edice Enterprise, která s sebou přináší i technickou podporu. Tato edice je určena zejména pro potřeby větších firem. Stejně jako u OpenShift Origin je produkt instalován na hardware zákazníka ať již v datovém centru nebo v privátním Cloudu13.

12. 13. Označení privátní Cloud se používá pro popis Cloud computingového řešení zřízeného za firemním firewallem výhradně pro firemní potřeby.

13 Kapitola 4 Webové aplikace psané v Ruby

Ruby je interpretovaný skriptovací programovací jazyk. Byl primárně vytvořen za účelem zvýšení produktivity a lepšího požitku z progra- mování, díky jeho jednoduché syntaxi a celkové přívětivosti. Podporuje několik paradigmat. Zejména objektově orientované, ale také impera- tivní či funkcionální. Ruby nebylo primárně vytvořeno za účelem vysoké rychlosti, proto se neřadí k nejrychlejším jazykům. V počátcích nebylo Ruby příliš známé a používané. Vydání první verze frameworku Ruby on Rails v roce 2005 napomohlo tuto skuteč- nost změnit. Firma Apple se pak následně rozhodla tento framework zahrnout do svého operačního systému. To znamenalo pro Ruby velký posun vpřed, hlavně ve vývoji webových aplikací. Než budeme dále pokračovat, vysvětlím nejdůležitější pojmy vázané k jazyku Ruby. Slovem gem se označuje knihovna, která je ve většině případů dostupná ke stažení z veřejného repozitáře RubyGems. Gem si můžeme představit jako JAR soubor používaný v jazyce Java. Dalším důležitým pojmem je Bundler. Jedná se o gem používaný v projektech ke správě závislostí. V souboru Gemfile stačí deklarovat projektem pou- žívané gemy a Bundler se postará o jejich instalaci a následnou správu.

4.1 Webové frameworky

Při vývoji webových aplikací se používají webové frameworky, které poskytují vhodné nástroje a knihovny usnadňující vývoj webové apli- kace. Vhodnost použití webového frameworku závisí vždy na rozsahu a typu projektu. Vybral jsem dle mého názoru dva nejdůležitější webové frameworky psané v Ruby, Ruby on Rails a Sinatra.

14 4. Webové aplikace psané v Ruby 4.1.1 Ruby on Rails Ruby on Rails1 je webový framework psaný v Ruby, který je open source. Je vhodný jak pro menší, tak i větší webové aplikace. Jeho prvotní verzi vytvořil dánský programátor David Heinemeier Hansson. Framework vznikl jako vedlejší produkt při tvorbě projektu Basecamp. Dosud se na vývoji Ruby on Rails podílelo přes tři tisíce lidí [8]. Ruby on Rails využívá architekturu Model View Controller (MVC) a jeho filozofie je postavena na dvou principech. Prvním je Don’t re- peat yourself (DRY). Tento princip říká, že duplikace kódu je špatná a měli bychom se jí vyhnout. Pomáhá k tomu vhodná struktura vytvo- řené aplikace pomocí tohoto frameworku. Druhým použitým principem je Convention over Configuration (CoC), díky kterému Ruby on Rails nevyžaduje specifikovat veškeré implementační detaily, ale automaticky je vyhodnotí na základě předpokladů. Pokud se například model jme- nuje Post, pak Ruby on Rails automaticky očekává, že název tabulky v databázi bude posts. Toto chování lze explicitně změnit.

4.1.2 Sinatra Ruby on Rails může být na menší projekty zbytečně složitým řešením. Zde přichází vhod Sinatra2. Minimalistický webový framework psaný v Ruby, který poskytuje jednoduché Domain specific language (DSL) rozhraní pro tvorbu webových aplikací. Použitím webového frameworku Sinatra můžeme vytvořit i rozsáhlejší webové aplikace, avšak bude po- třeba čelit problémům, které například Ruby on Rails má vyřešené již v základu. Sinatra nevyužívá architekturu MVC tak jako většina webových frameworků. Rozhodnutí nad použitou architekturou nechává plně na programátorovi, tak jako celkovou strukturu aplikace, proto je Sinatra výsadou zejména zkušenějších programátorů.

4.2 Implementace jazyka Ruby

Každá implementace Ruby má jiné vlastnosti. Liší se zejména rychlostí, paměťovými nároky a podporou paralelismu.

1. 2.

15 4. Webové aplikace psané v Ruby V této kapitole se věnuji popisu implementací jazyka Ruby, které jsem uvážil jako nejdůležitější. Jedná se o referenční implementaci ja- zyka Ruby, implementaci pomocí jazyka Java zvanou JRuby a imple- mentaci Rubinius.

4.2.1 Ruby MRI a Ruby YARV Ruby MRI (Matz’s Ruby ) je považováno za referenční imple- mentaci jazyka Ruby. Mezi hlavní vývojáře se řadí mimo jiné i , známý pod přezdívkou Matz, tvůrce jazyka Ruby. Zde se veškerá nová funkčnost jazyka Ruby objevuje jako první, ostatní im- plementace jazyka Ruby vždy tento náskok pouze dohánějí. Kód Ruby MRI byl od verze 1.9 nahrazen implementací zvanou Ruby YARV (Yet Another Ruby VM), někdy také označována jako KRI (Koichi’s Ruby Interpreter). Ruby MRI je stejně jako Ruby YARV psáno v jazyku . Ruby YARV oproti Ruby MRI provede po vy- parsování syntaktického stromu jeho převedení do malých úseků byte kódu [9], které pak následně spouští. Právě díky této změně dosahuje vyšší rychlosti, v některých případech až čtyřnásobné [10]. Další im- plementační změny jsou minimální, proto pokud níže srovnávám další implementace Ruby s Ruby YARV, mám automaticky na mysli i Ruby MRI. Obě tyto implementace obsahují Global Interpreter Lock (GIL). GIL zamezuje sdílet kód, který není vláknově bezpečný, s ostatními vlákny. Na každý proces spuštěného interpretu je vždy právě jeden GIL. To v praxi znamená, že není možné využít výkonu na více já- drových procesorech, protože v rámci GIL může být zpracováno pouze jedno vlákno v daném okamžiku. Tento problém se řeší využitím para- lelismu pomocí spuštění více stejných procesů navzájem komunikujících pomocí zpráv ukládaných do fronty [11]. Stejný princip využívá většina moderních webových serverů pro webové aplikace v jazyce Ruby. Jazyk Ruby negarantuje, že základní třídy jsou vláknově bezpečné. Důvodem by byla potenciální přidaná komplexita do jádra jazyka Ruby, která by měla za následek pomalejší vyhodnocení jedno vláknových operací [12]. Díky použití GIL jsou všechny Ruby metody implemento- vané nativně v jazyku C atomické [13]. Není však dobrým nápadem na toto spoléhat, kód se pak stává závislý na dané implementaci, ostatní implementace Ruby mohou přinést neočekávané výsledky.

16 4. Webové aplikace psané v Ruby 4.2.2 JRuby Jedná se o implementaci jazyka Ruby nad Java Virtual Machine (JVM) napsanou převážně v jazyce Java. Úzké propojení s jazykem Java umož- ňuje z kódu psaného v Ruby volat třídy z jazyka Java a naopak. JRuby na rozdíl od Ruby YARV podporuje plnohodnotný paralelis- mus. Z vlákna vytvořeného v Ruby se stane díky JRuby vlákno v Javě, které je pomocí JVM namapováno jako nativní vlákno [13]. Mezi další výhody JRuby oproti Ruby YARV patří lepší Garbage collector [14]. Zejména díky těmto důvodům, stabilitě díky JVM a úzkému propojení s jazykem Java, je JRuby oblíbeno u produkčních serverů a zejména při provozování enterprise aplikací. JRuby však není vhodné pro použití ve všech případech, zejména pokud se jedná o spuštění skriptů, které jsou časově nenáročné a zároveň nevyužívají více vláken. Ve většině těchto případů nabídne Ruby YARV mnohem větší výkon. Samotný čas spuštění skriptů totiž v JRuby ve srovnání s Ruby YARV zabere mnohem více času. Dobu spuštění lze zkrátit úpravou nastavení JVM, avšak u jiných typů úloh toto může vést ke snížení výkonu [15]. Nevýhodou u webových serverů v případě použití JRuby je potřeba zahřívací doby, než je webový server schopen rychle zpracovávat požadavky. Zahřívací doby u Ruby YARV potřeba není. Některé gemy v jazyce Ruby obsahují skripty v jazyce C, ty však již nadále nejsou od JRuby 1.7 podporovány. Jedná se zejména o webové servery, rozhraní komunikující s databází nebo také o parsery. Vět- šina těchto problémových gemů má alternativy psané přímo v jazyce Java [16].

4.2.3 Rubinius Rubinius tak jako JRuby neobsahuje GIL a podporuje plnohodnotný paralelismus. Zajímavostí u této implementace je, že kompilátor a téměř celá specifikace jazyka Ruby je psána přímo v jazyce Ruby, kterou Ru- binius zpracovává jako běžnou Ruby aplikaci. Samotné jádro implemen- tace Rubinius je psáno v jazyce C++. Rubinius pro kompilaci využívá Just in time (JIT) kompilátor implementovaný na základě projektu LLVM. Myšlenkou této dynamické kompilace je vytvořit verzi kódu v závislosti na aktuální běhu, která dosáhne stejného výsledku použi-

17 4. Webové aplikace psané v Ruby tím méně vynaložených prostředků, tedy i kratší doby zpracování [17]. Znatelnou výhodou implementace Rubinius jsou oproti Ruby YARV dobře čitelné zdrojové kódy obsahující i stručné komentáře.

4.3 Webové servery

Webový server je software, který přijímá požadavky od prohlížeče přes protokol HTTP. Ty následně předá webové aplikaci ke zpracování. Webová aplikace vrátí výsledek platný pro obdržený požadavek, který je následně webovým serverem zaslán prohlížeči jako výsledek jeho po- žadavku. V této kapitole se věnuji popisu webových serverů, které jsou při- dány v rozšíření Ruby cartridge, jenž je výstupem této práce. Všechny níže uvedené webové servery jsou spustitelné nad webovými aplikacemi podporujícími Rack. Rack je jednoduché rozhraní sloužící ke komunikaci mezi webovým serverem a webovým frameworkem. Toto rozhraní je použito u mnoha webových frameworků, včetně Ruby on Rails a Sinatra. Každý webový server uvedený níže podporuje spuštění více procesů (cluster) pro vyřešení problému s omezením GIL.

4.3.1 Thin Webový server Thin3 interně využívá parser z webového serveru Mon- grel a gem Event Machine4. Event Machine je knihovna umožňující provádět souběžné vstupně výstupní operace, které jsou řízeny pomocí událostí. Použitím Event Machine může webový server Thin během prová- dění vstupně výstupních operací zpracovávat další požadavky. Pokud například uživatel nahrává soubor do webové aplikace, tak během me- zery mezi úseky posílaných dat, webový server Thin zpracovává další požadavky na webovou aplikaci.

3. 4.

18 4. Webové aplikace psané v Ruby Thin není vhodný pro zpracování pomalých připojení5, v tomto pří- padě je vhodné na pozadí využít webový server Thin společně s webo- vým serverem Nginx.

4.3.2 Puma Puma6 ve svém jádru využívá parser psaný v jazyce Ragel převzatý z webového serveru . Puma byla primárně vytvořena pro im- plementace podporující plnohodnotný paralelismus, tedy Rubinius a JRuby. Běží ale i na Ruby YARV, kde díky interní správě vláken do- káže v rámci jednoho procesu provádět neblokované vstupně výstupní operace. Webový server poskytuje pro implementaci JRuby gem psaný přímo v jazyku Java.

4.3.3 Unicorn Unicorn7 využívá parseru z webového serveru Mongrel, tak jako Puma a Thin. Na rozdíl od webového serveru Thin není postaven na architek- tuře řízené zasíláním událostí, proto v rámci jednoho procesu nemůže webový server Unicorn provádět další požadavky souběžně se zpraco- váváním vstupně výstupních operací. Je psán v jazyku Ruby a částečně C. Unicorn využívá copy-on-write Garbage collector pro zmenšení vyu- žité operační paměti v případě více spuštěných procesů pro zpracování požadavků.

4.3.4 Passenger Webový server Passenger8 podporuje zapojení s webovým serverem Apache nebo Nginx, může ale fungovat i samostatně. Na rozdíl od

5. Dle HTTP protokolu je HTTP požadavek vyřízen až v době obdržení všech dat od webového serveru klientem. Připojení, které disponuje pomalou přenosovou rychlostí nebo vysokou latencí bývá označováno jako pomalé připojení. Toto připo- jení nutí webový server alokovat hardwarové zdroje, které nejsou po dlouhou dobu využity. Cílené zneužití tohoto faktu může vést až k Denial of service [18] (DoS). 6. 7. 8.

19 4. Webové aplikace psané v Ruby webových serverů uvedených výše funguje i pro webové aplikace psané v jazyku Python, Node.js. Jeho jádro je psáno v jazyku C++. Umož- ňuje zpracování více požadavků v jeden moment díky použité hybridní událostmi řízené architektuře [19].

4.4 Podpora webových aplikací v Ruby u platforem

V tabulce níže srovnávám platformy na základě jejich podpory pro webové aplikace psané v Ruby, konkrétně podporované webové servery, podporované implementace Ruby a podporu pro WebSockets.

OpenShift CloudFoundry Heroku Webové servery Passenger libovolný libovolný Implementace Ruby YARV Ruby YARV JRuby, Rubinius a Ruby YARV WebSockets ne ano ano

Dle tabulky Heroku disponuje nejlepší podporou pro webové apli- kace psané v jazyku Ruby, následovaná platformou CloudFoundry. Plat- forma OpenShift zaostává ve všech porovnávacích aspektech. Cílem této práce je tento fakt změnit.

20 Kapitola 5 Advanced Ruby catridge

Výstupem této práce je cartridge s názvem Advanced Ruby cartridge, která byla vytvořena za podpory firmy Red Hat. Zdrojové kódy spo- lečně s návodem na instalaci a použití jsou dostupné ve veřejném Git repozitáři1. Advanced Ruby cartridge vychází z oficiální Ruby cartridge, na- víc přináší podporu pro změnu použitého webového serveru a také umožňuje použití implementace JRuby. V budoucnu se minimálně část Advanced Ruby cartridge stane součástí oficiální Ruby cartridge, tak jako poznatky získané při vývoji této cartridge. V současné době tato cartridge funguje jako komunitní, tedy není dostupná v základu platformy OpenShift. Platforma OpenShift klade velký důraz na zpětnou kompatibilitu, proto jsem se v této práci snažil tento požadavek maximálně dodržet. Aplikace, které používají výchozí Ruby cartridge fungují i při použití Advanced Ruby cartridge. Výchozí hodnoty pro webový server a výchozí implementaci Ruby jsou stejné jako v případě oficiální Ruby cartridge. Advanced Ruby cartridge může v současné době běžet pouze na OpenShiftu, který běží na operačním systému Red Hat Enterprise Li- nux (RHEL). OpenShift Origin má podporu i pro operační systém Fe- dora, zde však tato cartridge neběží, jelikož veškerý vývoj probíhal na virtuálních strojích právě s operačním systémem RHEL. Vyřešení tohoto problému by nemělo být náročné. Díky vhodně zvolené abs- trakci by mělo stačit upravit pouze funkci ruby_context nacházející se v lib/ruby_context, a manifest cartridge. Ruby je u RHEL k dispo- zici přes Softwarové kolekce [20], ty se spravují příkazem scl. Softwarové kolekce v současné době u RHEL nabízejí Ruby ve verzi 1.9.3, zatímco u operačního systému Fedora je Ruby použito ve verzi 2.0.

1.

21 5. Advanced Ruby catridge 5.1 Struktura cartridge

Původně byl kontrolní skript pro ovládání webového serveru Passen- ger uložen přímo v kontrolním skriptu, který ovládá celou cartridge. Se zvýšeným počtem podporovaných serverů byla provedena restruktura- lizaci této logiky. Kontrolní a instalační skripty, společně s konfigurač- ními soubory pro každý webový server, jsou nyní umístěny v adresářové struktuře cartridge do složky servers. Ta je dále dělena na další složky podle názvů webových serverů. Každý webový server pak obsahuje kon- trolní skript pojmenovaný control a skript, který obsahuje příkazy pro instalaci webového serveru pojmenovaný install. Další soubory jako konfigurační soubory jsou libovolné a odvíjí se od potřeb daného ser- veru. Díky této navržené struktuře je budoucí přidání dalších webových serverů jednoduché a intuitivní, tak jako úprava konfigurace webového serveru.

5.2 Volba webového serveru a implementace Ruby

Zvolení webového serveru a implementace Ruby probíhá použitím uži- vatelských proměnných. Uživatelské proměnné u platformy OpenShift jsou proměnné, které mohou být nastaveny webové aplikaci. Spravují se příkazem rhc env. Webová aplikace nebo cartridge mohou z těchto proměnných číst. Uživatelské proměnné používá Advanced Ruby cartridge pro zvo- lení webového serveru a zvolení implementace Ruby. Pro zvolení webo- vého serveru se používá proměnná s názvem OPENSHIFT_RUBY_SERVER a pro zvolení implementace Ruby OPENSHIFT_RUBY_PLATFORM. Nejdříve byla u této cartridge použita pro zvolení webového serveru proměnná OPENSHIFT_SERVER, tedy bez příznaku RUBY. Ideou bylo, že tato pro- měnná se v budoucnu stane standardem i u ostatních jazyků, které budou umožňovat přepnutí webového serveru. Na podněty vývojářů pracujících na platformě OpenShift však byl k této proměnné přidán příznak RUBY, zejména z důvodu lepší budoucí udržovatelnosti. Uživatelské proměnné jsou novou funkcí na platformě OpenShift. V prvotních verzích Advanced Ruby cartridge se pro přepínání webo- vého serveru používal marker. Jedná se o soubor ukládaný v kořeno-

22 5. Advanced Ruby catridge vém adresáři projektu do složky .openshift/markers/. Například pro spuštění webového serveru Puma se musel vytvořit prázdný soubor .openshift/markers/puma a pak následně bylo potřeba nahrát tuto novou verzi webové aplikace na platformu OpenShift. Nahrávat novou verzi webové aplikace kvůli změně webového serveru není přijatelné, dříve však jiná možnost nebyla. Jakmile byly uživatelské proměnné vy- dány jako nová funkcionalita platformy OpenShift, použil jsem je jako lepší řešení.

5.3 WebSockets

Oficiální Ruby cartridge nepodporuje WebSockets [21]. Jedná se o pro- tokol hojně používaný moderními webovými aplikacemi. Použitím Web- Sockets může webový prohlížeč zachytit událost poslanou webovým ser- verem téměř v reálném čase. Dříve by se pro získání nových událostí z webového serveru použil HTTP polling, tedy periodické dotazování z webového prohlížeče na webový server přes protokol HTTP. HTTP polling oproti použití WebSockets zatěžuje mnohem více webový ser- ver a doba doručení události závisí na četnosti dotazování. WebSockets naproti tomu udržují perzistentní připojení mezi webovým serverem a webovým prohlížečem, které je použito pro obousměrné zasílání udá- lostí v reálném čase. Celý tento protokol je založen na vzoru Publish- subscribe2. Důvodem, proč oficiální Ruby cartridge nepodporuje WebSockets je zejména použití webového serveru Apache běžícího na pozadí webového serveru Passenger. Webový server Apache nebyl vytvořen pro správu mnoha perzistentních připojení. Jelikož Advanced Ruby cartridge při- náší podporu pro další webové servery, které nejsou limitovány webo- vým serverem Apache, je možné využít výhod protokolu WebSockets při použití webového serveru Thin, Puma nebo Unicorn. Pro demonstraci funkčnosti WebSockets jsem vytvořil ukázkovou webovou aplikaci3. Využívá jazyku Ruby (použit je framework Sinatra), jazyku JavaScript a HTML5.

2. 3.

23 5. Advanced Ruby catridge 5.4 Podporované implementace Ruby

Advanced Ruby cartridge podporuje referenční implementaci jazyka Ruby (Ruby YARV) a implementaci JRuby. Referenční implementace Ruby je předinstalována na každé komponentě Node, JRuby nikoli. Při instalaci cartridge se spustí skript bin/install, ve kterém se JRuby stáhne ze souborového serveru Amazon S34, který se nachází v rámci stejné sítě jako OpenShift Online, proto doba stažení je minimální. Stažení je provedeno do dočasného adresáře OPENSHIFT_RUBY_DIR/tmp, poté je přesunuto do domovského adresáře gearu do složky .. Toto řešení není optimální, jelikož JRuby zabírá na gearu místo. Pokud by měla být podpora pro JRuby přidána do oficiální Ruby cartridge, pak je potřeba na komponentě Node zajistit podporu pro JRuby. V případě operačního systému RHEL by se jednalo o přidání podpory pro JRuby do Softwarových kolekcí. Přepínání implementací Ruby se interně provádí uvnitř funkce zvané update-configuration, která se nachází v souboru lib/util. Tato funkce se volá při nahrání nové verze webové aplikace. Platforma OpenShift je z velké části psána v Ruby. Integrace im- plementace JRuby, která funguje spolu s referenční implementací Ruby proto nebyla jednoduchá. Jedním z problémů bylo nemožnost globálně pro gear upravit proměnnou GEM_HOME, která určuje místo, kam se uklá- dají nainstalované gemy. Gemy mohou být pro každou implementaci různé, proto je potřeba je ukládat v různých destinacích. Z toho dů- vodu je nutné spouštět každý Ruby příkaz skrze funkci ruby_context. Ta spustí příkaz ve správném kontextu na základě běžící implemen- tace Ruby. Gemy pro implementaci JRuby se ukládají do speciálního adresáře OPENSHIFT_DEPENDENCIES_DIR. Inspiraci pro toto řešení jsem čerpal z cartridge pro jazyk PHP. Referenční implementace Ruby má nastaveno ukládat gemy v domovském adresáři do složky .gems, distri- buce této složky do ostatních gearů je prováděna na základě interních skriptů platformy OpenShift. Původně jsem chtěl přidat podporu i pro implementaci Rubinius, o které si myslím, že by mohla přinést výkonnostní zrychlení. Malá velikost gearu disponující 512 MB operační paměti, ale na kompilační proces implementace Rubinius nestačila. Při použití středního gearu,

4.

24 5. Advanced Ruby catridge kde je možno využít 1024 MB operační paměti, již sice proces kom- pilace nenarážel na limit operační paměti, nicméně i v tomto případě celá instalace cartridge skončila chybou. Tentokrát z důvodu překročení časového limitu. V budoucnu bych chtěl, aby Advanced Ruby cartridge podporovala implementaci Rubinius. Uvažuji nad ruční kompilací implementace Ru- binius pro OpenShift a umístěním výsledných dat do veřejného repo- zitáře. Při instalaci Advanced Ruby cartridge by pak předpřipravená implementace Rubinius byla stažena a následně propojena s kontrol- ními skripty cartridge.

5.5 Podporované webové servery

Podporované webové servery u Advanced Ruby cartridge jsou Thin, Puma, Unicorn a Passenger. Implementace webového serveru Passen- ger je shodná s implementací u výchozí Ruby cartridge pro zajištění maximální zpětné kompatibility. Advanced Ruby cartridge umožňuje použití i jiného webového ser- veru, který není podporován v základu. Stačí pro server vytvořit kon- trolní skript se spustitelným příznakem. Ten umístíme v kořenovém adresáři projektu do složky .openshift/action_hooks/ pod názvem server_control a poté nastavíme hodnotu custom do uživatelské pro- měnné OPENSHIFT_RUBY_SERVER. Změna použitého webového serveru se projeví při novém spuštění Advanced Ruby cartridge. Tedy při jejím ručním zastavení a spuštění, nebo při nahrání nové verze webové aplikace. Implementace JRuby nepodporuje gemy minimálně částečně psané v jazyku C. Proto servery jako Thin, Passenger a Unicorn nejsou im- plementací JRuby podporovány. Z implementovaných webových serverů má podporu pro JRuby pouze webový server Puma. V budoucnu uva- žuji nad přidáním podpory alespoň jednoho webového serveru výhradně pro JRuby, který je postaven na aplikačním serveru JBoss nebo Tomcat. Jedná se například o webové servery TorqueBox5 a Trinidad6. Původní ideou přidání podpory webových serverů bylo vytvoření malé cartridge pro každý webový server, která by se nainstalovala na

5. 6.

25 5. Advanced Ruby catridge již nainstalovanou oficiální Ruby cartridge a překryla by tak webový ser- ver Passenger. Toto řešení však nefungovalo, ze dvou důvodů. Prvním důvodem je hluboká integrace webového serveru Passenger do kompo- nenty Node, ovládání tohoto serveru z další cartridge bylo složité a vy- žadovalo hodně technik pro obejití těchto podmínek. Druhým důvodem byla nemožnost spustit webový server na přidělené IP adrese a portu z nově nainstalované malé cartridge. Cartridge, která může využívat tuto IP adresu a port, musí být v manifestu cartridge definovaná jako web_framework. Taková cartridge může být však na gearu nainstalo- vána právě jednou, v tomto případě to je právě oficiální Ruby cartridge. Nainstalování další cartridge, která může využít přidělenou IP adresu a port pro spuštění webového serveru není možné, proto tato idea byla zavržena. Použité současné řešení pomocí jedné komplexní Ruby car- tridge zamezuje duplikaci kódu a usnadňuje udržovatelnost cartridge, proto v konečném důsledku se jeví jako lepší řešení.

26 Kapitola 6 Srovnávací výkonnostní testy

V této kapitole se věnuji srovnání rychlosti webových serverů při pou- žití testovací webové aplikace. Výkon se testuje na platformě OpenShift Online při použití Advanced Ruby Cartridge. Hlavním cílem této práce nebylo důkladné výkonnostní srovnání webových serverů, nýbrž rozší- ření Ruby cartridge, proto výkonnostní srovnání webových serverů je částečně zjednodušeno. Dobou odezvy se rozumí čas v milisekundách (ms), který uplyne od odeslání požadavku do jeho zpracování. Čím je doba odezvy menší v porovnání s ostatními webovými servery, tím je webový server vý- konnější. Ve výkonnostním testování budeme měřit dobu odezvy pro každý webový server při použití stejné testovací webové aplikace, proto budeme moci říci, který webový server je v tomto případě nejvýkon- nější. To však nelze říci obecně, výkon webových serverů se může lišit v závislosti na webové aplikaci, použité verzi Ruby nebo třeba i na hardwarových specifikacích komponenty Node, na které gear, potažmo geary, běží. Z testů by však mělo být patrné, že je potřeba mít možnost volby nad použitým webovým serverem, protože rozdíly ve výkonu a stabilitě při větší zátěži nejsou zanedbatelné.

6.1 Testovací webová aplikace

Pro testovací účely jsem vytvořil testovací webovou aplikaci1 za použití frameworku Ruby on Rails ve verzi 4.0. Jedná se o jednoduchý blog, který na úvodní straně zobrazí 10 článků s testovacími daty načtenými z databáze MySQL. Celá tato webová aplikace byla přizpůsobena pro produkční prostředí, jedná se zejména o úpravu nastavení ukládání bě-

1.

27 6. Srovnávací výkonnostní testy hových záznamů, povolení poskytování statických souborů a zvýšení možného aktivního počtu připojení k databázi. Testovací webová aplikace podporuje jak referenční implementaci Ruby, tak implementaci JRuby. Pro implementaci JRuby bylo zapotřebí přidat podmíněné závislosti do souboru Gemfile a přidat načtení ovla- dače JDBC pro databázi MySQL do souboru config/application.rb. Webová aplikace používá databázi MySQL. Původně jsem chtěl po- užít databázi MariaDB, na kterou z databáze MySQL díky zpětné kompatibilitě přechází mnoho firem, včetně firmy Google [22]. Mari- aDB však v současné době není dostupná u varianty OpenShift Online, pouze u OpenShift Origin.

6.2 Testovací metodika

Pro testování výkonu webových serverů jsem použil nástroj Apache- Bench2. Jedná se o testovací nástroj určený pro testování výkonu webo- vých serverů, který je spouštěn skrze terminál. ApacheBench byl zvolen zejména díky jeho jednoduchosti a zároveň dostatečné funkčnosti. Zvažoval jsem i použití nástroje JMeter3, který nabízí na rozdíl od ApacheBench grafické rozhraní a také mnohem větší funkčnost. Gra- fické rozhraní mi však nepřišlo jako uživatelsky přívětivé a příliš mnoho funkčnosti tohoto testovacího nástroje mě namísto samotného testování nutilo neustále číst jeho dokumentaci, proto jsem se rozhodl tento ná- stroj nevyužít. Srovnávací výkonnostní testy byly spouštěny z virtuálního stroje o velikosti m1.large4 vedeného u služby Amazon EC2. Tedy v rámci stejné lokální sítě, kde běží i OpenShift Online. Latence je v tomto případě rovna 5 ms, propustnost lokální sítě se pohybovala okolo 250 Mbps. Pokud bychom prováděli testování pomocí internetového připo- jení z České republiky, pak latence dle mého testování je v rozsahu od 120 ms do 220 ms, to by mohlo mít negativní dopad na průběh celého testování. Testujeme výkon webového serveru, proto latence musí být minimální a nejlépe i konstantní.

2. 3. 4. 2 virtuální procesory, 7,5 GB operační paměti a dva pevné disky o velikosti 420 GB

28 6. Srovnávací výkonnostní testy Test výkonnosti webového serveru se skládal ze dvou fází. V první fázi se provedlo zahřátí webového serveru pomocí 10000 · n požadavků, počet souběžných požadavků byl roven 10 · n, kde n je počet využitých gearů webovou aplikací. V druhé fázi se provádělo měření výkonu, které bylo spuštěno vždy desetkrát. Výsledkem byl průměr z jednotlivých mě- ření. Jednotlivé měření výkonu spočívalo v postupném odesílání 5000 požadavků na webovou aplikaci, kde počet souběžných připojení se lišil v závislosti na konkrétním testu. Všechny požadavky byly směřovány na kořenovou adresu testovací webové aplikace. Prodleva mezi jednot- livými testy činila 60 sekund. U webové aplikace využívající 1 gear probíhaly testy pro 1, 10 a 30 souběžných spojení. U 5 gearů se jednalo o 1, 45 a 90 souběžných spojení a u webové aplikace využívající 10 gearů byly testy spuštěny pro 1, 90 a 180 souběžných spojení. Za účelem automatizace testování výkonu webových serverů při po- užití Advanced Ruby cartridge jsem vytvořil jednoduchou aplikaci5 psa- nou v Ruby. Interně pro měření využívá nástroj ApacheBench. Výsledky byly do grafů zpracovány v tabulkovém editoru Numbers. Webová aplikace běžela na Ruby ve verzi 1.9.3, v případě JRuby se jednalo také o Ruby ve verzi 1.9.3. JRuby bylo použito ve verzi 1.7.9 a běželo na OpenJDK Server VM 1.7.0_45. Verze webových serverů byly následující: Puma 2.6.0, Thin 1.6.1, Unicorn 4.7.0 a Passenger 3.0.21.

6.3 Použitá konfigurace webových serverů

Nejvhodnější konfigurace webového serveru závisí zejména na hard- warovém zázemí. Konfigurační soubory, které jsou součástí Advanced Ruby cartridge, jsou vybrány jako nejvhodnější pro službu OpenShift Online. Byly vybrány na základě vlastního testování, které není obsa- hem této práce. Níže uvádím několik nabytých poznatků. Nemá cenu vytvářet několik procesů pro webový server, abychom předešli omezení GIL u referenční implementace Ruby. Limit pro využití procesoru u jednoho gearu je natolik malý, že webový server, potažmo webová aplikace, nedokáže z tohoto řešení přinést žádné rychlostní zlep- šení. Z toho vyplývá, že GIL, který je součástí referenční implementace Ruby, nijak neomezuje v případě platformy OpenShift Online poskyto-

5.

29 6. Srovnávací výkonnostní testy vaný výkon. Pokud je potřeba větší výkon, využijeme škálování. Žádný webový server neměl při použití testovací webové aplikace problémy s nedostatkem operační paměti, ani u malé velikosti gearu. Rozdíly ve velikosti gearů jsou popsány v podsekci 3.5.2 OpenShift Online. Nabízí se otázka, zda webové aplikace psané v Ruby nabídnou větší výkon při použití většího gearu. Dle mého testování nenabídnou, pokud dostupná operační paměť webové aplikaci dostačuje. Příkazem rhc ssh APP_NAME –-gears ”ps aux”, kde APP_NAME je rovno názvu webové aplikace, si můžeme zobrazit, kolik jednotlivé procesy na kaž- dém gearu zabírají operační paměti. Pokud paměť dostačuje, pak je cenově výhodnější zvolit malou velikost gearu.

6.4 Výsledky výkonnostního srovnání

Během testování se webový server Thin choval nestabilně. Pokud po- čet souběžných požadavků dosáhl počtu okolo 25 a více na jeden gear, webový server Thin se v mnoha případech samovolně vypnul. Proto testy u webového serveru Thin musely být spouštěny dodatečně manu- álně. Příčina nebyla zjištěna, v běhových záznamech webového serveru Thin nebylo nic nalezeno, různé změny konfigurace nestabilní chování neodstranily. Při testování škálovatelné aplikace jsem narazil na mnoho problémů s OpenShift Online, zejména s přidáním dalších gearů. Škálování bylo pro samotné testování nastaveno jako manuální za účelem přesné spe- cifikace počtu gearů. Navzdory tomu, že pokaždé po nastavení počtu gearů byla vypsána chyba ohledně vypršení časového limitu požadavku na komponentu Broker, tak v některých případech byly geary korektně vytvořeny. Někdy byl však navíc potřeba následný restart webové apli- kace. Stejný problém se objevoval i při použití jiné cartridge. U vari- anty OpenShift Origin jsem tento problém nezaznamenal. V případě automatického škálování, které spouští geary v závislosti na aktuálním počtu příchozích požadavků, vše fungovalo korektně, nový gear byl při náhlém nárůstu příchozích požadavků automaticky vytvořen do 15 mi- nut. Stav jednotlivých gearů a jejich aktuální zatížení lze zobrazit na ad- rese /haproxy-status/. Jedná se o jednoduchou webovou stránku po- skytovanou HAProxy. Během testů byla průběžně kontrolována. Kromě

30 6. Srovnávací výkonnostní testy odhalení nestabilního chování serveru Thin jsem žádné další problémy nezaznamenal, vyvažování zátěže mezi geary pomocí HAProxy bylo rov- noměrné. Testování probíhalo na malém gearu, který disponuje ope- rační pamětí o velikosti 512 MB.

6.4.1 Výsledky při vypnutém škálování

Webová aplikace byla spuštěna na jednom gearu společně s MySQL databází.

Passenger Puma Thin Unicorn Puma JRuby

2500 2321 2303 2153

2000 1918 1794

1500

1000

rnádoba odezvy [ms] 769 ě 681 692

m 643

ů 585

Pr 500

76 65 65 65 70 0 1 10 30 Počet souběžných dotazů

Nejkratší průměrné doby odezvy dosáhl webový server Unicorn ná- sledovaný webovým serverem Puma. Ačkoli výkon webových aplikací běžících na JRuby je pomalejší v porovnání s referenční implementací Ruby [23], tak JRuby si v tomto testu vedlo dobře. Výkon webového serveru Puma běžícího na implementaci JRuby byl srovnatelný s výko- nem webového serveru Passenger, který běžel na referenční implemen- taci Ruby. Použití webového serveru Unicorn oproti webovému serveru Passen- geru přineslo 23% zrychlení.

31 6. Srovnávací výkonnostní testy 6.4.2 Výsledky při zapnutém škálování na 5 gearů

Webová aplikace celkově využívala 5 gearů. Jeden gear pro MySQL databázi, druhý gear pro HAProxy a zbylé tři geary byly použity pro zpracování požadavků webovou aplikací.

Passenger Puma Thin Unicorn Puma JRuby

2504 2600 2431 2435 2245 2124

1950

1300 1152 1201 1170 997 952 rnádoba odezvy [ms] ě

m 650 ů Pr

122 107 118 92 115 0 1 45 90 Počet souběžných dotazů

Čas zpracování jednoho požadavku stoupl v průměru o 43 ms. Může za to zejména větší režie, kdy každý požadavek musí jít nejprve přes gear s HAProxy a poté až na další gear s webovou aplikací. Umístění databáze MySQL na samostatný gear nepřineslo žádné zrychlení. Během testování jsem narazil na zajímavý poznatek. Na primárním gearu, kde by mělo běžet jen HAProxy, byl spuštěn i webový server. Nebyly na něj posílány žádné příchozí požadavky, jen konzumoval hard- warové zdroje, které mohli být využity právě pro potřeby HAProxy. Do- mnívám se, že toto chování platformy OpenShift není korektní a proto bylo nahlášeno jako potenciální chyba.

32 6. Srovnávací výkonnostní testy 6.4.3 Výsledky při zapnutém škálování na 10 gearů V tomto případě využívala webová aplikace 10 gearů následovně: 1 gear pro databázi MySQL, 1 gear pro HAProxy a zbylých 8 gearů pro zpracování požadavků webovou aplikací.

Passenger Puma Thin Unicorn Puma JRuby

2500 2172 2105 2099 2000 1930 1889

1500

998 1032 1002 1000 924 870 rnádoba odezvy [ms] ě m ů

Pr 500

121 106 118 96 117 0 1 90 180 Počet souběžných dotazů

Výsledky mají podobnou tendenci jako při použití 5 gearů, horizon- tální škálování funguje spolehlivě. Průměrná doba odezvy závisí téměř lineárně na počtu použitých gearů pro zpracování požadavků webo- vou aplikací. Rozkládat zátěž mezi geary nedělalo HAProxy ani u 180 souběžných požadavků žádný problém, zatížení primárního gearu ob- sluhujícího HAProxy bylo minimální. Z výsledků je patrné, že čím větší zátěž na webovou aplikaci, tím rozdíly v průměrné době odezvy jsou menší. Důvodem je gear obsluhu- jící databázi MySQL, větší prodleva při zpracování dotazů způsobovala lehké vyrovnání naměřených výsledků. Při ještě větší zátěži by se z něj mohlo stát úzké hrdlo celé webové aplikace. V současné době MySQL cartridge nepodporuje škálování.

33 Kapitola 7 Závěr

Cílem práce bylo navrhnout funkční rozšíření pro Ruby catridge, která obsahuje podporu pro implementaci JRuby a umožňuje výběr z několika webových serverů. Následným úkolem bylo srovnat výkon použitých webových serverů při použití vytvořené cartridge spolu s vytvořenou testovací aplikací na platformě OpenShift. Ve druhé kapitole se věnuji stručnému představení Cloud compu- tingu a zasazení platformy OpenShift do kontextu. Další dvě kapitoly věnuji podrobnějšímu popisu platformy OpenShift a stručnému úvodu do webových aplikací psaných v jazyku Ruby. Vytvořené rozšíření pro Ruby cartridge nazvané Advanced Ruby cartridge je popsáno v páté kapitole. V šesté kapitole srovnávám výkon webových serverů. Práce mi umožnila seznámit se s platformou OpenShift. Zejména s jejím vývojem, na kterém bych se chtěl v budoucnu minimálně u open source varianty OpenShift Origin podílet. Umožnila mi získat mnoho nových kontaktů, prohloubit znalosti jazyka Ruby a seznámit se s im- plementací JRuby. Advanced Ruby catridge splňuje požadavky uvedené v zadání, navíc přináší podporu pro webové servery, které nejsou dostupné v základu cartridge. Advanced Ruby cartridge zaplňuje mezeru mezi platformou OpenShift a platformou Heroku v podpoře webových aplikací psaných v Ruby. Vytvořená cartridge a získané poznatky ohledně problematiky webových serverů, budou použity při budoucím vývoji oficiální Ruby cartridge. Ve svém volném čase se budu na vývoji Advanced Ruby car- tridge nadále podílet, minimálně do doby, kdy oficiální Ruby cartridge bude nabízet podobnou funkčnost. Výkonnostní srovnání webových serverů dokazuje, že možnost volby použitého webového serveru může ovlivnit celkový výkon a stabilitu webové aplikace. Ačkoli výkon webových aplikací běžících na JRuby je

34 pomalejší v porovnání s referenční implementací Ruby [23], tak webový server Puma běžící na JRuby nabídl srovnatelný výkon s webovým ser- verem Passenger běžícím na referenční implementaci Ruby. Webový server Thin se při větším počtu souběžných požadavků choval nesta- bilně. Literatura

[1] MELL, P.; GRANCE, T. The NIST Definition of Cloud Computing [online]. 2011 [cit. 2013-11-20]. Dostupné z: .

[2] QUICK, R. 5 reasons enterprises are frightened of the cloud [online]. 2013 [cit. 2013-10-20]. Dostupné z: .

[3] DARROW, B. More proof that Amazon still leads the IaaS pack, but watch out for those other dogs [online]. 2013 [cit. 2013-10-24]. Dostupné z: .

[4] OpenShift Origin System Architecture Guide [online]. 2013 [cit. 2013-10-25]. Dostupné z: .

[5] Scale your Applications on the Web | OpenShift by Red Hat [online]. 2013 [cit. 2013-10-25]. Dostupné z: .

[6] Deploying and Building Applications | OpenShift by Red Hat [online]. 2013 [cit. 2013-10-28]. Dostupné z: .

[7] Security Information | OpenShift by Red Hat [online]. 2013 [cit. 2013-11-20]. Dostupné z: . [8] Rails Contributors - All time [online]. 2013 [cit. 2013-12-03]. Do- stupné z: . [9] OLSEN, R. Eloquent Ruby. 1. vyd. Boston: Addison-Wesley Pro- fessional, 2011. ISBN 0321584104. [10] Ruby 1.8 vs. 1.9 Benchmarks [online]. [cit. 2013-11-10]. Dostupné z: . [11] MATSUMOTO, Y.; FLANAGAN, D. The Ruby . 1. vyd. New York: O’Reilly Media, 2008. ISBN 0596516177. [12] STORIMER, J. Nobody understands the GIL [online]. 2013. [cit. 2013-11-15]. Dostupné z: . [13] SHAUGHNESSY, P. Ruby Under a Microscope: An Illustrated Gu- ide to Ruby Internals. 1. vyd. San Francisco: No Starch Press, 2013. ISBN 1593275277. [14] SHAUGHNESSY, P. Learning More About JRuby from Charles Nutter [online]. 2012. [cit. 2013-12-03]. Dostupné z: . [15] Improving startup time [online]. 2013. [cit. 2013-12-03]. Dostupné z: . [16] C Extension Alternatives [online]. 2013. [cit. 2013-12-04]. Dostupné z: . [17] SHIRAI, B. 5 Things You’ll Love About Rubinius [online]. 2009. [cit. 2013-11-29]. Dostupné z: . [18] BEAVER, K. Why You Need To Pay Attention To The Slow HTTP Attack [online]. 2013. [cit. 2013-12-15]. Do- stupné z: . [19] design architecture [online]. 2013. [cit. 2013-12- 05]. Dostupné z: .

[20] Software Collections Guide [online]. 2013. [cit. 2013-12- 01]. Dostupné z: .

[21] Try Out Low-Latency Connections with WebSockets [online]. 2012. [cit. 2013-11-21]. Dostupné z: .

[22] PROFFITT, B. Google Waves Goodbye To MySQL In Favor Of MariaDB – ReadWrite [online]. 2013. [cit. 2013-12-05]. Do- stupné z: .

[23] KUKLOVÁ, K. Porovnání výkonu Ruby a JRuby ve webových apli- kacích [online]. 2011 [cit. 2013-12-10]. Bakalářská práce. Masary- kova univerzita, Fakulta informatiky. Vedoucí práce Martin Kuba. Dostupné z: . Přílohy

• openshift-advanced-ruby-cartridge - rozšíření Ruby cartridge

• test-app - webová aplikace psaná ve frameworku Ruby on Rails použitá při výkonnostním srovnání webových serverů

• websockets-example - webová aplikace pro demonstraci funkč- nosti WebSockets