Przejdź do treści
Zaktualizowano: 7 min czytania

Scala i model aktorowy — kiedy język funkcyjny na JVM jest właściwym wyborem

Scala i model aktorowy jako decyzja architektoniczna: jaki koszt ponosi zespół, w którym współdzielony stan psuje się pod obciążeniem, kiedy ten stos jest właściwą odpowiedzią, kiedy nie jest, jakie są alternatywy i ile kosztuje utrzymanie.

Klaudia Janecka Autor: Klaudia Janecka

Scala to język łączący programowanie obiektowe z funkcyjnym na maszynie wirtualnej Javy, a model aktorowy to sposób budowania systemów, w którym stan mieszka wewnątrz odizolowanych jednostek wymieniających komunikaty. Decyzja o tym stosie rzadko dotyczy składni. Dotyczy tego, ile organizacja zapłaci za przewidywalność systemu, w którym wiele rzeczy dzieje się naraz.

Na skróty

Czego dowiesz się z artykułu:

  • Jaki koszt organizacja ponosi, zanim ktokolwiek zaproponuje zmianę języka albo modelu programowania
  • Jakie warunki muszą wystąpić razem, żeby ten stos był właściwą odpowiedzią
  • W jakich sytuacjach nie odpowiada on na realny problem
  • Jakie alternatywy pozostają i jaką cenę niesie każda z nich
  • Co organizacja podpisuje na lata, wchodząc w ten ekosystem

Dla kogo ten artykuł:

  • Architekci rozstrzygający, gdzie mieszka stan systemu i jak jest chroniony
  • Kierownicy zespołów odpowiadający za tempo dostarczania i za nocne wezwania
  • Menedżerowie planujący budżet kompetencji i rekrutacji na lata

Jaki koszt ponosi zespół, w którym współdzielony stan psuje się pod obciążeniem?

Rachunek nie zaczyna się od nazwy języka. Zaczyna się od defektów, których nikt nie umie odtworzyć: zamówienie policzone podwójnie, saldo zaktualizowane w złej kolejności, blokada zatrzymująca wątki dopiero wtedy, gdy ruch przekroczy zwykły poziom. Takie usterki nie wychodzą w testach, bo test wykonuje po jednej rzeczy naraz. Wychodzą w godzinach szczytu, kosztują wezwanie dyżurnego i kończą się poprawką, która chroni miejsce zgłoszenia i nie mówi nic o pozostałych.

Do tego dochodzi koszt cichy, płacony codziennie: gdy poprawność zależy od dyscypliny każdego programisty przy każdej zmianie, tempo zmian spada. Zespół obudowuje kod blokadami na zapas, a przegląd kodu zamienia się w polowanie na wyścigi. Rosnący koszt zmiany jest tu wcześniejszym objawem niż awaria.

Problem ma odmiany, a ich pomylenie jest najdroższym błędem tego rozdziału. Pierwsza odmiana to wiele zdarzeń dotykających tego samego bytu: rachunku, magazynu, sesji abonenta. Problemem jest wtedy porządek i izolacja, a nie moc obliczeniowa. Druga odmiana to duży wolumen danych przetwarzanych niezależnie, gdzie rekordy nie walczą o wspólny stan — to jest problem przepustowości i rozwiązuje się go innymi narzędziami. Widać to najostrzej w rozliczeniach, telekomunikacji i systemach przyjmujących zdarzenia z urządzeń: pomyłka między porządkiem a przepustowością kosztuje tam przepisanie architektury po roku.

Kiedy język funkcyjny i model aktorowy są właściwą odpowiedzią?

Ten stos jest właściwą odpowiedzią wtedy, gdy występują razem trzy warunki, a nie gdy spełniony jest którykolwiek z nich osobno:

  • Stan jest współdzielony i sporny. Ten sam byt zmienia się z wielu źródeł jednocześnie, a kolejność zmian ma znaczenie biznesowe. Model aktorowy daje wtedy jednostkę, która przetwarza komunikaty pojedynczo, więc porządek jest własnością konstrukcji, a nie umową między programistami.
  • Niezmienność jest do przyjęcia jako domyślna. Struktury danych, których nikt nie modyfikuje w miejscu, znoszą całą klasę wyścigów, ale wymagają innego sposobu pisania kodu i innego sposobu myślenia o wydajności. Zespół, który tego nie chce, będzie obchodził język zamiast go używać.
  • System ma przetrwać awarię części, a nie całości. Nadzór nad jednostkami, restart poddrzewa i rozproszenie stanu na kilka węzłów są warunkiem, a nie ozdobą. Jeżeli akceptowalną odpowiedzią na błąd jest restart całej usługi, ta maszyneria zostanie kosztem bez pokrycia.

Dopiero gdy te warunki występują łącznie, sensu nabiera nauka samego modelu: hierarchie nadzoru, obsługa komunikatów, strumienie z kontrolą przepływu i praca w klastrze. Ten zakres — od pierwszego aktora po rozproszenie i odporność na awarie — obejmuje szkolenie Akka — od początkującego do średniozaawansowanego.

Kiedy tej technologii nie wybierać?

Najczęstszym błędem jest sięgnięcie po model aktorowy w imię skalowalności, zanim ktokolwiek zmierzył, gdzie system faktycznie się zatyka. Kolejka komunikatów przed jednostką, która czeka na bazę danych, nie przyspiesza niczego — przenosi wąskie gardło w miejsce trudniejsze do zaobserwowania.

Poza tym są sytuacje, w których ten stos nie odpowiada na realny problem. Aplikacja, której logika sprowadza się do zapisu i odczytu z bazy, ma współbieżność rozstrzygniętą poziom niżej: transakcja i blokada bazy danych robią tam robotę, a warstwa aktorów dokłada wyłącznie własną semantykę do zrozumienia. Przetwarzanie dużego wolumenu rekordów, które nie walczą o wspólny stan, jest zadaniem dla silnika przetwarzania danych, a nie dla modelu opartego na tożsamości i porządku komunikatów. Zespół bez kompetencji funkcyjnych i bez planu ich zbudowania dostanie kod, który wygląda jak dawny język zapisany nową składnią, i zapłaci za utrzymanie dwóch stylów naraz zamiast jednego. Żadnej z tych trzech sytuacji nie zmienia to, ile pracy już włożono w wybór narzędzia. Punktem odniesienia dla kosztu kompetencyjnego jest tu język, który na tej samej maszynie wirtualnej ma najszerszą bazę specjalistów — rozkłada go tekst o programowaniu w Javie i kompetencjach zespołów IT.

Jakie są alternatywy i ile kosztują?

Pozostanie przy języku zastanym i sięgnięcie po nowsze mechanizmy współbieżności maszyny wirtualnej nie wymaga zmiany ekosystemu ani rekrutacji, ale zostawia ochronę stanu w rękach dyscypliny zespołu: to samo, co dziś zawodzi, ma zadziałać dlatego, że zostanie zapisane staranniej. Rozdzielenie systemu na osobne usługi komunikujące się przez brokera zdejmuje spór o pamięć, a w zamian wystawia rachunek operacyjny — utrzymanie brokera, obsługę powtórzonych komunikatów i idempotentność operacji. Biblioteka reaktywna w dotychczasowym języku daje część korzyści bez zmiany składni, ale płaci się za nią diagnostyką: ślad stosu przestaje odpowiadać przebiegowi programu.

Ostatnia droga bywa najtańsza i najrzadziej rozważana: usunięcie współbieżności tam, gdzie nie jest potrzebna — pojedynczy właściciel danego bytu, kolejka przed nim i przetwarzanie po kolei. Bywa też jedyną, która działa, bo pozostałe zakładają, że równoległość jest wymaganiem, a nie nawykiem. Koszt rozcięcia systemu na niezależnie wdrażane części rozkłada przewodnik po architekturze mikroserwisów.

Co organizacja podpisuje na lata, wchodząc w ten ekosystem?

Podpisuje przede wszystkim zależność od cyklu życia biblioteki, a nie tylko od języka. Warstwa aktorowa dostępna dziś komercyjnie ma też odgałęzienie rozwijane w fundacji jako projekt otwarty, więc wybór między nimi jest decyzją o dostawcy i o warunkach licencji, a nie wyborem interfejsu programistycznego. Ta decyzja wraca przy każdej większej aktualizacji i trzeba mieć dla niej właściciela.

Podpisuje też koszt narzędziowy: dłuższą kompilację, zgodność binarną powiązaną z wersją języka i węższy ekosystem bibliotek. Najdroższą pozycją nie jest jednak żadna z tych rzeczy, tylko kompetencja. Kod napisany przez osobę, która odeszła, a którego nikt w zespole nie czyta swobodnie, zamienia się w obszar, gdzie zmiany są odkładane. Rolą, która ten rachunek obniża, jest zespół rozumiejący język na tyle, żeby czytać cudze rozwiązania — czyli zakres szkolenia Programowanie w Scala — od podstaw do zaawansowanych technik. Bez tego organizacja płaci podwójnie: za wybraną technologię i osobno za każdą zmianę w kodzie, którego nie umie utrzymać.

FAQ — najczęściej zadawane pytania

Czy model aktorowy przyspieszy nasz system?

Sam z siebie nie. Przyspiesza go usunięcie wąskiego gardła, a model aktorowy porządkuje dostęp do stanu i nie zmienia czasu odpowiedzi bazy danych ani przepustowości sieci. Jeżeli pomiar wskazuje na zasób zewnętrzny, zmiana modelu programowania przesunie problem, zamiast go rozwiązać.

Czy trzeba przepisać cały system, żeby skorzystać z tego podejścia?

Nie. Maszyna wirtualna pozwala uruchamiać nowy kod obok dotychczasowego, więc typową drogą jest wydzielenie fragmentu, w którym spór o stan jest najostrzejszy. Ryzykiem nie jest technologia, lecz granica: jeżeli przebiega w złym miejscu, zespół utrzymuje oba style programowania naraz i żaden nie daje pełnej korzyści.

Po czym poznać, że problem jest w porządku zdarzeń, a nie w wydajności?

Po kształcie awarii. Problem wydajnościowy rośnie płynnie razem z obciążeniem i widać go w opóźnieniach. Problem porządku pojawia się skokowo, dotyczy pojedynczych rekordów i nie daje się odtworzyć na żądanie. Ta druga klasa nie znika po dołożeniu maszyn.

Klaudia Janecka
Klaudia Janecka Opiekun szkolenia

Poproś o ofertę

Rozwiń swoje kompetencje

Sprawdź naszą ofertę szkoleń i warsztatów.

Zapytaj o szkolenie
Zadzwoń do nas +48 22 487 84 90