• Nebyly nalezeny žádné výsledky

„Návrhové vzory jsou znovu použitelná řešení pro vývoj softwaru. Fungují jako šablony, které může vývojář použít při tvorbě aplikací. Nejsou určené pro specifické programovací jazyky, ale používají se jako best practices či obecná pravidla, která mohou být využita napříč různými vývojovými prostředími.“ (Sharpen Productions, 2021)

Jak je možné z definice vyčíst, návrhové vzory nemusí být určeny pro programovací jazyky.

V mnoha případech jsou spojeny s určitou technologií. Ve velké části z nich se vyskytuje popis tříd, a tudíž se vážou na objektově orientované programovací jazyky (Java, C# atd.).

Každý návrhový vzor by měl popisovat, jaká je motivace (problém), která za ním stojí, dále by měl obsahovat samotný popis možného řešení.

Návrhové vzory se dělí na tři typy:

• Tvořivé

• Strukturální

• Chování

Tvořivé vzory se zaměřují na tvorbu jednotlivých objektů v systému pro specifický případ a na to, kolik právě tohoto objektu má v systému být. Mezi příklady patří Jedináček (omezení počtu instancí na jednu) nebo Abstraktní továrna (spojení rodiny objektů, které mezi sebou nějak souvisí).

Strukturální vzory se pak starají o vztahy jednotlivých tříd, částí kódu či objektů.

Příkladem může být Adaptér (upravuje třídy pro potřeby jiné) či Dekoratér (přiděluje dynamicky odpovědnosti jiným objektům)

Vzory chování jsou zaměřeny na komunikaci mezi jednotlivými objekty, také napomáhají s jejich flexibilitou. Příkladem může být Řetěz povinností (pomáhá s řízení dotazu skrz více objektů) dále Příkaz (parametrizace požadavků pro jejich lepší rozdělení).

Pro lepší vysvětlení bude použit příklad. Vývojář aplikace spravuje databázi a chce uživateli poskytnout možnost ji používat, zároveň ovšem nechce, aby v ní prováděl změny. Motivací

je tedy umožnění uživateli aplikace přístup k databázi s omezenými právy, není žádoucí, aby mohl vidět citlivá či smazat důležitá data. Využít lze tedy návrhový strukturální vzor Proxy, kterým radí v tomto případě vytvořit zástupný či dočasný objekt, kterému budou přidělena oprávnění. Ta budou vyhovovat stanoveným potřebám a neohrozí data jiných uživatelů. I toto řešení přináší jisté nedostatky, například pak zpomalení odpovědi či větší složitost kódu díky novým objektům. Ovšem ochrana proti nezodpovědným uživatelům a usnadnění pochopení kódu díky použití zdokumentovaných řešení, tyto problémy převyšují (Alexander Shvets, 2021).

2.2 Co jsou architektonické vzory

„Architektonický vzor je obecné, znovu použitelné řešení k často se vyskytujícímu problému v softwarové architektuře v daném kontextu. Tyto vzory často popisují několik možný problémů při vývoji softwaru. Například jak řešit limitace počítačového hardwaru, zajistit vysokou dostupnost a minimalizovat rizika pro byznys.“ (Taylor et al., 2009)

Na rozdíl od návrhových vzorů se tento druh zabývá tím, jak je celá aplikace sestavena a jak její části na sebe navazují, spolupracují nebo mezi sebou komunikují. Ať už je to rozdělení jednotlivých aplikací do několika vrstev. Příkladem může být rozdělení do 4 vrstev a to prezenční, aplikační, byznysové a datové. Dalším příkladem poté může být vzor klient-server, peer-to-peer a mnoho dalších (Mallawaarachchi, 2020).

Tyto vzory se zaměřují na velké množství technologií v různých oborech IT. Oblasti, kterými problémy, kterými se mohou zabírat jsou: datová architektura, velikost služeb, analýza textu či různé způsoby rozhodování v oboru umělé inteligence.

2.3 Motivace pro Serverless návrhové vzory

V předchozí kapitole byly popsány jisté charakteristiky Serverless, tato část některé z těchto charakteristik využije jako motivaci pro návrhové vzory, které pomohou s řešením problémů, které se mohou objevit. K těmto 4 vzniklým kategoriím bude přidána pátá, která bude popisovat architekturu funkcí či celých aplikací na platformě.

• Architektura služby

• Zpoždění a dostupnost

• Vázání na poskytovatele

• Bezstavové a pomíjející

• Řízená událostmi

Tento list poslouží jako motivace pro návrhové vzory, které budou popsány více do hloubky, dále bude poukázáno na jejich možná využití. V této části nebudou popsány všechny nalezené vzory, pouze ty, kterých motivace souvisí s výše zmíněnými charakteristikami a řeší jejich problémy. Řeší zajímavý problém či základní potřebu pro provoz na tomto

modelu. Výjimkou jsou první 3 vzory, které se zabývají architekturou aplikace, zatímco navazující kategorie řeší specifický problém.

2.3.1 Architektura služby

Tato část je zaměřena především na to, jakou architekturu vybrat pro aplikace v Serverless světě nebo například pouze pro API. Narozdíl od zbylých kategorií se nebude jednat o to, jak strukturovat pracovní postup aplikace či jejích částí, nýbrž o to, jakým způsobem vytvořit architekturu aplikace. Důvodem pro používání jednotných vzorů architekturních vzorů je především snadné zaučení nových vývojářů a zvýšení přehlednosti u větších aplikací atd.

API neboli rozhraní pro programování aplikací umožňuje dvěma aplikacím komunikovat mezi sebou. Jako API se dá považovat také kontaktní místo, mezi někým, kdo informaci požaduje (dotaz) a někým, kdo informaci poskytuje (odpověď) (Red Hat, Inc, 2021).

Příkladem takového API může být dotaz, který bude obsahovat jméno a příjmení uživatele a jako odpověď přijde výpis uživatelů, který odpovídá těmto kritériím. V této práci se bude jednat o modelovou ukázku takového API na serveru za pomoci jednoduchých dotazů pro získání (GET), upravení (PATCH), vytvoření (POST) či smazaní (DELETE) dat z databáze.

Monolithic pattern (Monolitický vzor)

Zdroje: [(Rud, 2019), (Hefnawy, 2021), (Richardson, 2021), (Retter, 2020)]

Motivace: Rychlý vývoj, spuštění a otestování funkcionality

Řešení: Tento vzor zahrnuje všechen kód služby do jedné velké Lambda funkce či u jiných technologií jako jeden adresář. Využití pro tento vzor je především z důvodu rychlého vývoje a jednoduchosti propojení funkcí mezi sebou. Vyskytuje se tedy často u menších aplikací operujících na FaaS či na začátcích aplikací pro otestování funkcionality, takzvaný „proof of concept“ (Rud, 2019). Je zde také možné snížit šanci na „cold start“, kde díky častým dotazům bude funkce evidována jako „warm“, a tudíž nebude nikdy po delší dobu vypnuta a nebude nutné ji znovu inicializovat (Hefnawy, 2021).

U větších funkcí poté začnou být výhody zastíněny nevýhodami jako například:

• Zpomalení inicializace funkce na serveru

• Snížení přehlednosti funkce úměrně k velikosti

• Změny či chyby v částech kódu mohou způsobit dominový efekt ve zbytku aplikace

• Zbrzdění rychlosti vývoje více lidmi

Proto je možné najít tento kód v historii většiny služeb na dnešním trhu, příkladem je Netflix. Ovšem firmy z monolitického vzoru přecházejí na jiný druh architektury, protože se může stát něco podobného jako právě výše zmíněné společnosti (Richardson, 2021).

Netflixu v roce 2008 kvůli jedné chybě na několik dní nefungoval systém (Rud, 2019). Od té doby firma rozdělila svůj software na více jak 700 mikroslužeb a přesunula se na AWS s tím,

že využívá do určité míry i FaaS funkce například na rozdělení nahraných videí do 5minutových kousků pro další práci (Retter, 2020).

Microservice pattern (Vzor mikroslužeb)

Zdroje: [(SmartBear Software. 2021), (Hefnawy, 2021), (Benetis, 2017)]

Motivace: Velká škálovatelnost a odolnost vůči chybám

Řešení: „Architektura mikroslužeb neboli mikroslužby je způsob vývoje softwarových systémů, který se zaměřuje na stavbu samostatných funkčních modulů s definovanými rozhraními a operacemi.“ (SmartBear Software. 2021)

To v praxi znamená, že aplikace nejsou jedním velkým repositářem, kde se shromažďují všechny funkce, které aplikace obsahuje, ale jsou spíše rozděleny do jasně definovaných menších aplikací, které obstarávají nějakou část daného celku.

V případě API by se tedy jednalo o rozložení jednotlivých akcí nad databází na jednotlivé funkce. Na rozdíl od předchozího typu tedy budeme mít samostatnou Lambda funkci pro každou akci (Hefnawy, 2021).

Tento styl umožňuje bezpečný a přehledný systém pro produkční verzi aplikace, protože chyba v jedné funkci nezasáhne žádným zásadním způsobem ostatní části aplikace. Také zvyšuje agilitu vývoje díky tomu, že jednotlivé týmy či jednotlivci mohou jednoduše přidávat další funkcionalitu bez větších změn celé aplikace (Benetis, 2017). Napomáhá k urychlení hledání chyb díky tomu, že je přesně známo, odkud chyba přišla a lze očekávat většinou jeden druh odpovědi (Hefnawy, 2021).

Mezi nevýhody tohoto přístupu patří:

• Velký počet funkcí, obzvláště pak u FaaS, kde jsou funkce ještě menší než u běžných mikroslužeb

• Vetší šance na „cold start“ u méně užívaných funkcí

• Pomalé nasazení

Toto se může projevit v reálném světě například tím, že jedna mikroslužba bude u společnosti Netflix obstarávat profily seriálů, tedy část, kde se zobrazuje, kolik má seriál dílů, o čem je, kdo v díle hraje atd. Naopak jiná funkce se bude starat o jejich nahrávaní.

Díky tomuto řešení se již nestane, že služba, která se stará o nahrávání souborů přestane fungovat a nezřítí se celý systém, ale pouze jednu jeho část. Uživatel nemusí o tomto problému ve výsledku vůbec vědět.

Service pattern (Vzor služeb)

Zdroje: [(Hefnawy, 2021)]

Motivace: Vyšší přehlednost funkcí při zachování odolnosti vůči chybám

Řešení: Tento typ se dá nejsnáze využít nad NoSQL (Not only Structured Query Language) databází jako je například MongoDB, kdy lze rozdělit akce podle objektů. Na příkladu API bude každá Lambda funkce obstarávat jeden objekt, k němu pak všechny 4 akce (Hefnawy, 2021). Není potřeba vždy rozdělit funkce přes model, lze také každé funkcionalitě přidělit zvláštní funkci a její akce.

O tomto vzoru lze tedy říct, že se jedná o kombinaci monolitu s mikroslužbami, kdy kombinuje vyšší přehlednost, rychlejší nasazení, ovšem zároveň umožňuje vyšší odolnost vůči chybám a snazší práci více týmů na jiných částech aplikace. Další výhodou této architektury je vyšší šance, že funkce bude zachována jako teplá díky častějšímu volání (Hefnawy, 2021).

Problém tohoto stylu je ovšem v tom, že nedělá ani jednu z těchto věcí pořádně a za cenu výhod monolitu získává jeho jisté nevýhody.

• Složitější debuggování, díky většímu počtu možných odpovědí

• Větší funkce, a tudíž pomalejší inicializace Rozdíl mezi vzory

Obr 1 Ilustrace struktury jednotlivých vzorů, kruhy symbolizují Lambda funkce a jaké akce ovládají Nejsnazším způsobem, jak jednoduše vysvětlit rozdíl mezi těmito přístupy je poté přímo na kódu pro RESTful API. Tato API bude mít za úkol práci v databázi, a to nad tabulkami osoba a zvíře. Akce budou u obou tabulek stejné tedy pro vytvoření (POST), upravení (PATCH), smazání (DELETE) a nalezení (GET).

U monolitického vzoru by všechny tyto akce měla na starost jedna velká Lambda funkce.

Její výhodou by tedy byla eliminace častého cold startu, ovšem náročnější debugging a dá

se očekávat, že by byla i dražší. Tedy v monolitickém vzoru by každá služba využívala několik velkých Lambda funkcí.

Vzor služeb by měl dvě Lambda funkce. Každá z těchto funkcí by obstarávala všechny 4 akce nad každou tabulkou. Aplikace nad tímto vzorem by se tedy skládala z více středně velkých funkcí.

Posledně pak mikroslužby, kde by každá akce měla vlastní funkci a taková aplikace by se skládala z obrovského množství malých funkcí. Díky tomu se dá očekávat, že uživatel častěji narazí na cold start, ovšem vývojář získá mnohem snazší debugging a nezávislost celého systému.

2.3.2 Zpoždění a dostupnost

Studený start patří k těm nejznámějším charakteristikám pro veřejnost, především z důvodu, že ji uživatelé pociťují nejvíce kvůli delšímu času na spuštění u prvního dotazu na funkci. V této oblasti lze pozorovat pokrok, jelikož někteří poskytovatelé dokážou u

„rychlejších“ jazyků dosáhnout časů kolem jednotek sekund.

V dnešní době je podle společnosti Google doporučená doba na načtení stránky mezi 1 až 2 sekundami, kdy se šance na odchod uživatele po tomto časovém intervalu zvyšuje až o 60 procent (Google LLC, 2017). Pokud tedy společnost provozuje svůj web či jeho část na Serverless technologii a poskytovatel ho má zaevidovaný jako studený, tak se podstatně zvyšuje šance na odchod potenciálního zákazníka či uživatele. Jak tedy omezit dobu, za kterou se aplikace spustí nebo alespoň snížit dobu čekání uživatele na odpověď pro jeho dotazy?

Lambda warmer (Ohřívač funkcí)

Zdroje: [(Intent Solution Group, 2019), (Likness, 2020), (Serverless Heroes, Inc., 2017), (Neves, 2021), (Daly, 2020)]

Motivace: Omezení počtu studených startů a dobu, po kterou musí čekat.

Doba, za kterou jednotlivý poskytovatelé FaaS vypnou kontejner, ve kterém čeká funkce na událost, se liší. Ovšem většinou se pohybuje mezi 5 až 15 minutami, například pro AWS Lambda lze hovořit o intervalu mezi 5 až 7 minutami (Mikhail Shilkov, 2021b). Pokud se tedy bude jednat o méně používanou službu či bude slabší provoz, může se uživateli stát, že na studený start narazí hned několikrát, bude-li procházet více částí webu nebo ho procházet pomalu.

Řešení: Problém se dá řešit, pingováním této funkce v určitém časovém intervalu, aby se udržela teplá (Likness, 2020). Tento časový interval by měl ideálně být podobný jako je nejkratší možná doba, kdy poskytovatel vysadí kontejner s funkcí (Serverless Heroes, Inc., 2017). Například u služby AWS Lambda by to mělo být 5 minut. Ideální pro toto řešení je

využití Časovače (o tom později), který umožňuje v předem stanoveném intervalu zapnout funkci, a tudíž ji udržet naživu (Daly, 2020).

Alternativním řešením by mohlo být nahřátí funkce při vstupu na stránku, která předchází této funkci. Tedy pokud jsme na stránce o správě uživatelů, vyšleme ping na funkce, které spravují jednotlivé akce. Tento styl má nevýhodu u velkých aplikací, kdy se toto může stát nepřehledným.

Dalším způsobem, může být využití pluginu do používaného frameworku, který tento problém řeší bez zbytečné konfigurace na straně poskytovatele a udržuje funkce teplé pomocí nastavení přímo v kódu (Neves, 2021).

Tento vzor navýší cenu této Lambda funkce i přes velmi krátké volání, ovšem právě díky cenovému modelu, kdy se platí pouze za dobu, kdy funkce vypočítává, a ne za to, kdy čeká na dotaz, se toto řešení dá aplikovat, pokud existují obavy o možnou ztrátu zákazníků.

The Circuit Breaker (Jistič)

Zdroje: [(Daly, 2018), (Amazon Web Services, Inc, 2019b), (Coulter, 2020), (Bardsley et al., 2018)]

Motivace: Snížení času na odpověď při chybě

Jak bylo identifikováno v první kapitole, z charakteristik Serverless vychází, že jich velká část využívá mnoho API třetích stran. Tedy aplikace, které nespravuje samotný uživatel, pouze využívá jejich služeb pro své potřeby. Příkladem mohou být jednoduché API na získání současného kurzu až po složitější na získávání a upravování dat pracovníku v aplikaci na správu pracovní doby.

Čím více takových API tím více možných chyb v systému, z čehož vychází delší doba čekání na odpovědi, zároveň pak i výpočetní doba, za kterou poskytovatel FaaS platformy dostane zaplaceno. Jak tedy eliminovat možné vyhozené peníze při volání na zrovna spadlou API?

Řešením je vytvoření takzvaného Jističe

Řešení: Jistič bude sledovat počet chybných odpovědí ze strany API. Pokud překročí předem určený počet chybných odpovědí, tak automaticky začne vracet chybovou odpověď uživateli bez volání na API a po předurčeném intervalu se opět otevře. Ovšem nebude fungovat stejně jako za běžného provozu, protože šance, že stále nebude funkční, je poměrně velká. Po uplynutí tohoto intervalu se opět otevře tato cesta s menší kapacitou, tedy přibližně na 20 procent, a bude dále sledovat, zda je již v pořádku. Pokud se ukáže, že je API stále chybová, tak se opět zavře a restartuje se tento interval. Naopak, pokud se ukáže, že je již funkční, tak ji lze opět otevřít v plné síle a už není potřeba většině uživatelům vracet automatickou zprávu o chybě (Daly, 2018).

Zásadní výhodou tohoto řešení je snížení času, který aplikace prostojí při čekání na chybovou odpověď, a tedy placení za dobu běhu funkcí (Coulter, 2020). Díky tomuto řešení lze také předejít kritickým chybám a zbytečnému tvoření nových funkcí (Bardsley et al.,

2018). U Serverless rčení: „Čas jsou peníze“ platí dvakrát. Bohužel, toto není nejjednodušší řešení na implementaci, právě kvůli bezstavovosti Serverless. Tento vzor se tedy hodí především, pokud se jedná o aplikaci velmi vytíženou aplikaci s mnoha dotazy na pozadí.

V tomto případě bude peněžní ztráta z dlouhého prostoje značná.

Obr 2 Přeložený ilustrace možného postupu Jističe (Daly, 2018)

The Scalable Webhook (Do fronty)

Zdroje: [(Beswick, 2021), (Romero, 2019). (Daly, 2018), (Microsoft, 2018), (Zambrano, 2018)]

Motivace: Škálovatelnost dotazů na neškálovatelný server

Na AWS Lambda funkcích je nastavený výchozí limit počtu souběžně spuštěných funkcí na 1000 pro jeden region (Beswick, 2021). To znamená, že pokud funkce obdrží v jednu chvíli 2000 dotazů, polovina z nich automaticky obdrží chybový kód. Podobný problém také může nastat, pokud se jedná o méně agilní řešení, než jsou právě FaaS funkce, například klasické databáze, kde bývá limit nastaven na počet dotazů v jednu chvíli.

Řešení: Vytvořením fronty před samotným serverem a zamezení přetížení

Pokud mezi API bránu a funkci vložíme takzvaný frontový systém dosáhneme chtěného efektu. Tento systém umožní vytvořit z velkého počtu dotazů frontu, ve které bude několik menších balíčků dotazů, které jsou rozložené do delšího intervalu. Díky této frontě nebude zapotřebí odpovídat chybovou hláškou na tyto dotazy. Rozdělí tedy dříve zmíněných 2000 dotazů do menších balení, které je služba schopna obstarat, například 500.

Při využití Do fronty pro stabilizaci API lze pomocí frontové služby odeslat klientovi zprávu o zpracovávání jeho dotazu (202), kdy uživatel dostane vizuální odpověď. Následně je proveden dotaz v pozadí a jsou odeslána zpracovaná data ze serveru na uložený kód kontaktu s klientem (Romero, 2019) (Beswick, 2021).

Tento vzor slouží jako obrana aplikace především při náhlém externím nárůstu dotazů, proti potencionálnímu přetížení a následnému pádu, a to ať už se jedná o ochranu funkce vlastní či třetí strany (Microsoft, 2018). Tento vzor by neměl mít znatelný dopad na běžný provoz aplikace, ovšem poskytuje obrovskou výhodu při práci pod velkým náporem (Daly, 2018).

Frontou je poskytnuta větší odolnost, škálovatelnost a je umožňeno vývojářům předpovídat, pod jakým náporem budou pracovat jejich funkce a služby (Zambrano, 2018). Dále také existuje možnost ušetření za cenu služby, jelikož není potřeba nastavovat sílu funkce na maximální provoz, postačí nastavení provozu na běžný (Microsoft, 2018).

Problém pro frontové systémy pak tvoří synchronní dotazy, kdy dotazovatel očekává

Motivace: Nechceme být vázání na poskytovatele kvůli snaze o snížení výdajů

Takzvaný vendor lock-in může být problémem z mnoha důvodů, ať už se jedná o snahu o udržení nákladů na minimum, nespokojenost s dosavadním řešením či o snahu o využívání nových specifických technologií, které jiný poskytovatel neumožňuje.

Řešení: Tento problém lze řešit za pomoci frameworků, které umožňují automatizaci nahrávání kódu do různých řešení od Serverless poskytovatelů. Výběr tohoto frameworku bude probíhat za pomoci zjištění toho, které poskytovatele podporují (AWS, Microsfot, Google atd.) a jaké programovací jazyky jsou na nich dostupné (Node.js, Next.js, Python atd.). Po výběru frameworku a jazyka následuje nastavení jak na straně poskytovatele, tak ve vývojovém prostředí.

Existují dva druhy frameworků, jedny pracují s existujícími CC řešeními (Serverless Framework, Apex Up atd.) a druhé naopak vytváří vlastní Serverless prostředí (Apache OpenWhisk atd.).

První možný se nastavuje především pomocí souborů existujících v repositáři aplikace, tedy například typu JSON či YML (Serverless, Inc., 2021b). V těchto souborech se odehrává samotné nastavení různých služeb na straně poskytovatele. Zde lze nastavit, jaká práva může mít služba, pod jakým URL se aplikace zobrazí nebo to, jak se bude jmenovat úložiště se soubory a mnoho dalších podrobnějších nastavení. Nastavení toho, jaký účet bude pro tyto služby využit, se ukládá v souborech frameworku. Zde se odstraní další starosti s administrativou z toho důvodu, že o nahrání, nastavení a spuštění aplikace u poskytovatele se stará pouze jeden soubor a o ostatní se postará framework.

U některých frameworků jako Apex Up nebo Claduia.js vzniká problém, kdy je možnost nasadit tato řešení pouze na AWS Lambda. Toto je způsobeno především rozdělením společností přes poskytovatele Serverless prostředí, a to díky tomu, že 70 procent z nich využívá právě řešení od společnosti Amazon (Conway, 2017). V tomto nám tedy umožňuje skutečnou svobodu především Serverless Framework, který nabízí všechny hlavní hráče na poli Serverless (Serverless, Inc., 2021b).

Druhou možností je potom spuštění vlastního Serverless řešení na lokálním či veřejném serveru, kdy naopak lze získat zpět jistou kontrolu nad tím, jak se alokují prostředky pro aplikaci. Tento typ na rozdíl od předchozích vyžaduje více znalosti a má složitější zprovoznění, ovšem poskytuje větší kontrolu nad aplikací (The Apache Software Foundation, 2021). U Apache OpenWhisk, je zapotřebí ke spuštění Java, Docker a Node.js a lze ho mít funkční během několika minut, ovšem pro plné využití těchto služeb bude

Druhou možností je potom spuštění vlastního Serverless řešení na lokálním či veřejném serveru, kdy naopak lze získat zpět jistou kontrolu nad tím, jak se alokují prostředky pro aplikaci. Tento typ na rozdíl od předchozích vyžaduje více znalosti a má složitější zprovoznění, ovšem poskytuje větší kontrolu nad aplikací (The Apache Software Foundation, 2021). U Apache OpenWhisk, je zapotřebí ke spuštění Java, Docker a Node.js a lze ho mít funkční během několika minut, ovšem pro plné využití těchto služeb bude