Akka - wytłumaczenie na "chłopski rozum"

Odpowiedz Nowy wątek
2018-12-09 21:50
1

Zastanawia mnie kwestia projektowania aplikacji w Akkce (Scala). Chodzi mi o to, jak najlepiej traktować rolę aktorów. Czy dzielić aplikację w ten sposób, że każdy komponent jest osobnym aktorem, który jest odpowiedzialny za wykonywania jakichś, określonych zadań? Czy każda warstwa (kontrolery, logika, DAO, itd.) ma działać jako osobny aktor? Czy też jeszcze szerzej - każdy aktor to osobny mikroserwis w większym systemie, który porozumiewa się asynchronicznie z innymi? Jakie ma to porównanie z projektowaniem aplikacji znaym np. ze Springa?

Samą idee aktorów i jak działa Akka rozumiem. Chodzi mi o zastosowanie tego np. przy budowaniu aplikacji REST (Akka HTTP). Gdyby ktoś mógł to pokrótce wyjaśnić i (jeśli możliwe) wrzucić np. diagram przykładowej architektury.

Pozostało 580 znaków

2018-12-11 19:35
1

Kilka użyć, które mają sens:

  • Komunikacja asynchroniczna z stanem mutowalnym
  • Potrzeba skalowalności horyzontalnej (np. routery)
  • location transparency
  • Jakiś system z konkretnym schematem nadzorowania (supervision)

Na pewno jest ich znacznie więcej, to jest to co mi przyszło tak na szybko do głowy. Kilka rzeczy których nie powinno się robić (przynajmniej w moim odczuciu):

Pozostało 580 znaków

2018-12-11 20:39
2

Samą idee aktorów i jak działa Akka rozumiem. Chodzi mi o zastosowanie tego np. przy budowaniu aplikacji REST (Akka HTTP). Gdyby ktoś mógł to pokrótce wyjaśnić i (jeśli możliwe) wrzucić np. diagram przykładowej architektury.

Akka HTTP nie wymaga tworzenia własnych aktorów w ogóle. Owszem, jest zbudowana na aktorach i oferuje świetną integrację z aktorami, ale ja np stworzyłem w pracy mikroserwis oparty na Akce HTTP, a nie posiadający ani jednego własnego aktora. To kiedy zastosować aktory lub strumienie to decyzja raczej oddzielna od zastosowania Akki HTTP.

Akka HTTP wspiera backpressure, podobnie jak Akka Streams na których jest oparta. Połączenie tych dwóch bibliotek może dać bardzo fajne efekty (sam takie połączenie zrobiłem). Dla przykładu możesz stworzyć serwer HTTP, który:

  • przyjmuje od użytkownika dane, gzipuje je, a potem wysyła na NASa
  • przyjmuje od użytkownika zapytanie, robi zapytanie do bazy danych i strumieniuje je z powrotem do użytkownika
  • generuje dane losowe, bądź np liczby Fibonacciego w nieskończoność

Dzięki temu, że każdą z tych operacji można zaimplementować z obsługą backpressure to będzie miał to backpressure na całej długości. Oznacza to, że generowanie bądź transfer danych zostaną spowolnione jeżeli np CPU nie będzie wyrabiał z gzipowaniem, NAS nie będzie wyrabiał z zapisywaniem, użytkownik nie będzie wyrabiał z odbieraniem danych z bazy bądź danych wygenerowanych, itd Dodatkowo Akka Streams jak sama nazwa wskazuje strumieniują dane, a więc nie generujemy całych danych do wielkiego bufora, tylko generujemy je kawałek po kawałku. Stąd np możemy strumieniowo wysłać 10 GiB danych z bazy przy użyciu 1 megabajtowego bufora, czy też analogicznie przy takim samym buforze gzipować i zapisywać na NASa plik o rozmiarze 10 GiB albo generować losowe dane w nieskończoność (tzn aż klient przerwie ściąganie). Wszystko to bez blokowania wątków, tzn bez setek wątków czekających na IO (bo np 100 użytkowników naraz robi żądania).

* w rzeczywistości zrobienie jednocześnie 100 zapytań do bazy i wczytywanie danych jak najszybciej zwykle wymaga jednak 100 wątków przy użyciu JDBC. JDBC jest synchroniczne, a asynchronicznego standardowego API niestety Oracle jeszcze nie zrobiło. Chociaż z drugiej strony są niestandardowe asynchroniczne API np dla PostgreSQL czy MySQL: https://github.com/mauricio/postgresql-async


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 4x, ostatnio: Wibowit, 2018-12-11 20:47
Pokaż pozostałe 3 komentarze
Trudno dać jakąś krótką jednoznaczną odpowiedź na to kiedy używać Future'ów (czy też jakiegokolwiek asynca w Scali czy w innych językach). Na pewno Future się przydaje, by nie blokować wątków, czyli np jeśli robisz żądania HTTP gdzieś dalej. Z zapytaniami do bazy niestety jest tak, że JDBC jest synchroniczne, więc i tak któryś tam wątek musi być zablokowany. Z drugiej strony mamy jednak strumienie Akkowe i dzięki nim możemy np strumieniować ogromne ilości danych z małymi opóźnieniami, np dane z bazy, dysku czy innego serwera HTTP. - Wibowit 2018-12-16 02:13
Na tej stronie co podałem jest przykład ze strumieniem, który zwraca nieskończony ciąg losowych liczb. To od klienta HTTP zależy ile sobie ściągnie danych. Strumień jest buforowany, a bufor jest niewielki. Przetrzymuje trochę danych wygenerowanych naprzód, ale nie rośnie w nieskończoność. Jeśli klient wstrzyma ściąganie to strumień wstrzyma generowanie danych. Wracając do Future'ów i baz danych - dogłębnie nie analizowałem tematu. W CRUDzie łatwo zdecydować się na Future'y, bo Slick je generuje, więc można po prostu pociągnąć temat dalej. - Wibowit 2018-12-16 02:26
Dzięki za odpowiedzi. Trochę mi się to rozjaśniło, reszta wyjdzie w praktyce. MAsz moze jakiś przykładowy szkielet aplikacji w Akkce Http? Chodzi mi głównie o sensowne oddzielenie Main klasy od routes (dla różnych API) i serwisów. - Overkill 2018-12-17 21:49
Hmm, mam swój projekt, ale tam jest jedna klasa z routami. Serwer jest stawiany w https://github.com/tarsa/Sort[...]ServerBenchmarkSuiteApp.scala Routy są tworzone w https://github.com/tarsa/Sort[...]enchmarkSuiteController.scala . W linijce val bindingFut = Http().bindAndHandle(server.route, "localhost", 8080) widać przenoszenie server.route do serwera. Route można łączyć za pomocą ~ albo gotowcem Directives.concat. - Wibowit 2018-12-17 21:59
Dzięki, obadam. Szukam czegoś co pozwoli wejść w ten temat jak Spring Boot, ale póki co nic takiego nie znalazłem. A chce zrobić projekt, który będzie miał ręce i nogi - więc jakieś sensowne oddzielanie controllerów (rotesów) od reszty jest istotne. - Overkill 2018-12-17 22:03

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0