Sytuacja kobiet w IT w 2024 roku
1.04.20216 min
Pablo Iorio

Pablo IorioIT ArchitectZurich Financial Services

Zalety i wady architektury serverless w pigułce

Poznaj wady i zalety korzystania z serverless i zdecyduj, czy jest to rozwiązanie, z którego warto korzystać.

Zalety i wady architektury serverless w pigułce

Serverless polega na korzystaniu z zasobów komputerowych, które działają jako serwisy, bez potrzeby zarządzania fundamentalną infrastrukturą. Co więcej, nie oznacza to, że serwery nie odgrywają już żadnej roli. Sam termin odzwierciedla punkt widzenia programisty. 

Główne cechy

Mike Roberts zaproponował następujące kryteria, według których definiujemy serverless:

  • Hostami serwera i procesami nie zarządza klient, czy developer (wysokopoziomowa abstrakcja)
  • Elastyczność oznacza autoskalowanie i automatyczne przydzielanie zasobów na podstawie obciążenia
  • Płatność za to, czego się używa w zależności od oferty danego dostawcy
  • Rozmiar i liczba serwerów nie definiują wydajności
  • Domyślnie, wysoka dostępność i tolerancja na błędy 

Serverless = FaaS + BaaS 

Jak już osiągniemy powyższe, to możemy założyć, że serverless to nie tylko function as a service, ale również backend as a service (np. przechowywanie w chmurze, uwierzytelnianie, bazy danych). 

Co więcej, chciałbym Wam pokazać porównanie między różnymi modelami typu “as a service”, a tradycyjnym IT, gdzie cały stos znajduje się tam, gdzie się pracuje. Im dłuższa strzałka na poniższysz obrazie, tym więcej potrzeba zarządzania. 

Jak bardzo trzeba tak naprawdę zarządzać. Porównanie między różnymi modelami typu “as a service”.

Zalety architektury serverless


Płacisz tyle, ile używasz

Cena wynika z liczby żądań do Twoich funkcji. Zazwyczaj możliwe jest też skorzystanie z okresu próbnego, który jest za darmo. Jest to bardzo korzystne, jeśli chodzi o analizę kosztów. Zdaje mi się jednak, że dostawcy tworzą darmowe plany, by pozyskać nowych klientów. Podczas analizy kosztów/przychodów trzeba wziąć pod uwagę koszty migracji funkcji, usługi towarzyszące serverless (np. API Gateway, CDN, load balancery itd.) oraz dane.


Wbudowana elastyczność

Wszystko skaluje się automatycznie w zależności od dodawania i odejmowania zasobów. 


Produktywność

Z jednej strony taki typ architektury zapewnia na początku szybki developement, kiedy liczba funkcji jest ograniczona. A to dlatego, że nie trzeba wtedy martwić się o początkową konfigurację infrastruktury. Z drugiej jednak strony, duża liczba funkcji może znacznie utrudnić tę kwestię, zwłaszcza jeśli spojrzymy z testerskiego punktu widzenia oraz pod kątem debugowania. Opcją, która pozwoli nam mieć większą kontrolę nad rzeczami i może zwiększyć naszą wydajność, jest użycie emulatorów developmentu. Różnią się one jednak trochę od środowiska produkcyjnego, pomimo kilku podobieństw - jakaś funkcja może więc działać w emulatorze, ale nie na produkcji. 


Testy jednostkowe każdej funkcji z osobna są prostsze

A to ze względu na zasadę pojedynczej odpowiedzialności, która pozwala zredukować przestrzeń testową do minimum. Testy integracyjne mogą być jednak bardziej wymagające. 


Abstrakcje

Pomimo że wysokopoziomowe abstrakcje pomagają nam skupić się na złożoności w domenie biznesowej, to jednak łatwo jest utracić tutaj kontrolę. To jest niestety ten klasyczny trade-off w inżynierii oprogramowania. 


Model oparty na zdarzeniach 

Taka architektura istnieje już trochę czasu. Serverless idealnie do niej pasuje. Funkcje można łączyć przy pomocy "hooków". Na przykład, funkcja może być rozwinięta w taki sposób, aby przetwarzać niepowodzenie uwierzytelnianie z OAuth. Zasada otwarte-zamknięte zapewnia dobrze zdefiniowane interfejsy, które są w stanie rozszerzać rozwiązania bez zwiększania powierzchni testowej. 


Mikroserwisy

Korzystanie z funkcji umożliwia rozwijanie architektury opartej na mikroserwisach. Łatwiej jest wtedy rozwijać oddzielne komponenty, tak aby nie trzeba było dokonywać ich jednoczesnego deploymentu. Z drugiej jednak strony zwiększając liczbę elementów, zwiększamy złożoność, latencję oraz koszt utrzymania i monitorowania. Tutaj możesz dowiedzieć się więcej o operacyjnej złożoności mikroserwisów. 


Niemutowalność

Funkcji się nie modyfikuje, każda zmiana to nowa wersja. W przypadku stworzenia nowej wersji zaleca się monitorowanie użycia poprzedniej wersji i wyrzucenie jej, w momencie, kiedy już nikt jej nie używa. 


Izolacja i bezpieczeństwo 

Każda z funkcji może mieć jedynie dostęp do swojego własnego kontenera. Jeśli uruchomienie funkcji się nie powiedzieć, to nie będzie ona mogła mieć dostępu do innych kontenerów. 


Łatwiejsze tworzenie się nowych środowisk 

Dzieje się tak, kiedy kilka przepływów pracy działa równolegle, ponieważ tworzenie się wszystkich komponentów można zautomatyzować. 


Wsparcie dla teamów wielojęzycznych

Chodzi tutaj o wiele języków programowania. Funkcje mogą być wtedy wykonywane w JS, Pythonie, Go, w jakimkolwiek języku z JVM (Java, Clojure, Scala itd.) lub jakimkolwiek języku .NET. Pomaga to w lepszym dopasowaniu się do umiejętności zespołu i do implementowanych wymagań. 


Bezstanowe z natury 

Bezstanowość oznacza, że każde żądanie jest wykonywane w izolacji i nie przekazuje się między nimi stanu. Jest to bardzo korzystne, ponieważ daje nam elastyczność bez potrzeby zamartwiania się o stan. Co więcej, zmniejsza złożoność. Na rynku oferowane są też wersje, które przechowują stan - np. trwałe funkcje Azure, lub AWS step functions, które zawierają w sobie funkcje orkiestracyjne i umożliwiają definicję bardziej złożonych przepływów pracy.  


Domyślnie duża dostępność i tolerancja na błędy

SLA w AWS Lambda w każdym miesiącu i w każdym regionie to 99.95%. 

Wady i wyzwania


Podejścia hybrydowe

Podejście hybrydowe, w których korzystamy z chmury i serwerów on-premise, musi być ostrożnie przemyślane, ponieważ wszystkie elementy serverless będą domyślnie elastyczne, a elementy on-premise już takie nie są. W takim przypadku być może będzie trzeba użyć throttlingu, by nie przeciążyć infrastruktury, która się nie skaluje. 


Złożoność systemowa

Z jednej strony niektóre części systemu stały się prostsze. Z drugiej jednak, zwiększyła się złożoność, a to dlatego, że mamy więcej orkiestracji między funkcjami i serwisami, schematu wiadomości, więcej API, błędów sieci i tak dalej. Wymagane są dobre monitorowanie, rozpoznanie operacyjne i automatyzacja deploymentu, aby móc debugować cały system. 


Zamknięcie na określonego dostawcę 

Redukcja w przenaszalności. Mamy tutaj też ograniczony wybór, jeśli już zdecydowaliśmy się na danego vendora. Istnieją frameworki FaaS, które tworzą abstrakcję nad rozwiązaniami konkretnych dostawców, co zwiększa przenaszalność. Koszty migracji nadal mogą być duże. W większości przypadków nie wynikają one z różnic w kodzie samych funkcji, a w działaniu usług, które są użyte, by z funkcji stworzyć pełne rozwiązanie.


Ograniczenia zasobów

Funkcje mają swoje ograniczenia ze względu na alokację pamięci, zarządzanie limitem czasu żądania, rozmiar żądania, rozmiar samej funkcji i wykonanie współbieżne. Granice te są spójne z filozofią serverless. Dobrze sprawdzi się tutaj mała funkcja, z pojedynczą odpowiedzialnością, która jest uruchomiona przez krótki czas, nie zużywa dużo zasobów i jest małego rozmiaru. Jeżeli chcesz mieć proces działający dłużej i pożerający dużo pamięci, to inna architektura pewnie będzie lepsza.


Testy integracyjne są ciężkie 

Kiedy już dotrzesz to pewnego poziomu funkcji i będzie trzeba wykonać orkiestrację, to testy integracyjne stają się niezwykle wymagające. Staje się tak, kiedy nie masz kontroli nad wszystkimi serwisami, które istnieją wokół danego rozwiązania. Musisz wtedy tworzyć stuby tych serwisów. Jeśli vendor nie zapewnia takiej możliwości, to trzeba je samemu stworzyć. 


Debugowanie też jest ciężkie 

Replikacja chmury na lokalnej maszynie jest trudna. Nie chodzi tutaj o samą próbę, ponieważ dostawcy chmury powinni zapewniać opcje do debugowania w chmurze, uruchamiając repliki podobne do tych, które możemy spotkać na produkcji. Zobaczmy, w którą stronę pójdzie debugowanie w ciągu kilku następnych lat. 


Obserwowalność

Obserwowalność zawiera w sobie monitorowanie, alerty, gromadzenie logów i śledzenie wykonania w systemie rozproszonym. Monitoring i altery każdego serwisu są częścią usług dostawcy. Gromadzenie logów oraz śledzenie wykonania w systemie rozproszonym mogą oznaczać więcej pracy, zwłaszcza jeśli używa się zewnętrznych serwisów i gdzie to wszystko jest zebrane w jedną całość. Dzieje się tak, ponieważ nie można tutaj używać standardowych wzorców. Przetwarzanie w tle nie jest możliwe do zrealizowania. To samo tyczy się agentów i demonów, które działają w funkcjach. Dużo się w tym obszarze jednak dzieje, spodziewam się, że niektóre rzeczy mogą się poprawić. 


Cold start, lub wysoka latencja 

Kiedy jakieś zdarzenie uruchamia daną funkcję, jeśli się jej przez jakiś czas nie używało, to trzeba wtedy zainicjować instancję kontenera. Powoduje to opóźnienie między żądaniem a wykonaniem funkcji - czyli cold start. Będzie on zależał od kilku czynników - np. języka programowania, liczby linijek do wykonania, biblioteki do załadowania i innych rzeczy związanych z konfiguracją środowiska. 


Za bardzo ambitne API Gateway 

Jeden z problemów wskazanych przez ThoughtWorks Radar to sytuacja, w której warstwa gateway gromadzi zbyt dużo logiki biznesowej. Wie ona również o orkiestracji, która jest wymagana między różnymi funkcjami/serwisami. W konsekwencji trudniej się testuje i zmniejsza się przenaszalność.  

Podsumowanie

Mamy szczęście, że żyjemy w czasach pełnych nowych technologii i architektur, nawet jeśli alternatyw byłoby tyle, że będzie ciężko wybrać. Serverless pozwala na osiągnięcie bardzo dużej elastyczności, jeżeli chodzi o zasoby. Z drugiej strony w pewnych warunkach oznacza utratę kontroli.


Oryginał tekstu w języku angielskim możesz przeczytać tutaj.

<p>Loading...</p>