W ciągu ostatniego tygodnia zacząłem zajmować się tworzeniem oprogramowania, badając koncepcję wirtualnych aktorów. Ostatecznie zainteresowałem się dwoma różnymi frameworkami: Dapr i Orleans.
Oba projekty są bardzo zwięzłe i mają mnóstwo ciekawych zastosowań. Oba wykorzystują ideę "wirtualnych" aktorów. Aktor wirtualny to jednostka stanu i logiki, która:
- Można go jednoznacznie zidentyfikować za pomocą ID
- Jest jednowątkowy
- Może być w pamięci lub trwały – jego cykl życia jest zarządzany przez framework
Bardzo podoba mi się pomysł wirtualnych aktorów i uważam ich za bardzo pomocne w moich poszukiwaniach budowania skalowalnych i niezawodnych narzędzi do obsługi złożonych przepływów zadań. Jeśli każde zadanie jest pojedynczym wątkiem wirtualnym uczestnikiem, problem warunków wyścigowych znika.
Ponieważ Orleans i Dapr to oba projekty Microsoftu, wyobrażam sobie dzień w stylu Western Story w stołówce Microsoftu.
Orlean
Zacząłem od Orleans, bo od jakiegoś czasu miałem na nim uwagę po obejrzeniu kilku filmów na YouTube. Zaczęło się bardzo źle, bo myślałem, że będę używał wersji 4.x wszystkich ich pakietów NuGet. Jednak absolutnie żadna ich dokumentacja nie działa z pakietem 4.x. Ostatecznie użyłem wersji 3.6.2.
Ziarna / Stan / Liczniki czasu
Stworzenie ziarna, które śledzi swój stan i wykonuje działania, jest bardzo proste. Udało mi się nawet przejrzeć dokumentację dotyczącą trwałości ziarna i stworzyć własną implementację IGrainStorage w CosmosDB (SQL API).
Przypomnienia
Przypomnienia są też łatwe do ustawienia. Aż spróbowałem skonfigurować dla nich realistyczną trwałość. Na tym etapie moich badań staram się utrzymać wszystko w porządku i przechowywać wszystko w ComsosDB. Niestety, nie mogę w ogóle uruchomić pakietu persistence Orleans do przypomnień. Ostatecznie musiałem przejść na pakiet AzureStorage. Teraz moje dane są w połowie na koncie SQL API, a w połowie w koncie tabelowego API.
Strumieni
To tutaj nie poszło mi dobrze. W Orleans przepływy są identyfikowane za pomocą GUID oraz opcjonalnej przestrzeni nazw. Jestem pewien, że jest dobry powód, dla którego strumienie muszą być identyfikowane przez GUID, ale wow, to niepraktyczne.
Jestem bardzo sfrustrowany streamami, bo łatwo je tworzyłem, ale gdy zatrzymuję i restartuję projekt oraz wywołam nowe zdarzenie, wszystko się zawiesza.
Następnie dodaję bardzo cenną informację, bo zajęło mi 8 godzin, aby odtworzyć kod Orleans i to rozgryźć:
Gdy ziarno jest subskrybentem strumienia, ziarno musi wywołać ResumeAsync na kontakcie subskrypcji w swojej metodzie OnActivateAsync, inaczej wystąpi awaria z nierozpoznanym błędem.
Miałem też problem z duplikowaniem tej samej subskrypcji, więc użyłem kodu, aby usunąć wszystkie subskrypcje ziarna, a potem je odtworzyłem:
Inne wskazówki i wskazówki z Orleans
Streams dobrze współpracuje z Azure Event Hubs (za pośrednictwem AddEventHubStreams).
Nie używaj / ani innych specjalnych znaków w nazwie Grain w API SQL CosmosDB!
Zakończenie z Orleanu
Lubię Orleans i uważam, że ma potencjał. Jednak krzywa nauki jest bardzo stroma. Z powodu mojej długiej walki ze streamowaniem nie mam czasu, by studiować, jak działają klastry/wdrożenia.
Dapr
Znalazłem Dapr, szukając alternatyw dla Orleans. Trochę dziwne, że to także projekt sponsorowany przez Microsoft. Być może są tu, by przyjąć zasadę przetrwania najsilniejszych. Jeśli tak, myślę, że Dapr będzie ocalałym.
Po pierwsze, projekt Dapr oparty na REST/gRPC pozwala na implementację aktorów w dowolnym języku programowania. Uważałem też, że to banalne uruchamianie wszystkiego (uczestników, statusów, timerów, przypomnień, wydarzeń) na jednej instancji Redis. Na dodatek zajęło mi to tylko około jednej trzeciej czasu, żeby zacząć używać Dapr. Tak szybki start zawdzięcza doskonała dokumentacja Dapr.
Aktorzy / Timery / Przypomnienia
Czy właśnie powiedziałem, że dokumentacja Dapr jest świetna? Cóż, jest wszędzie, poza przykładami w JavaScript. Większość czasu spędzam na Dapr, próbując wymyślić, jak wywołać metody na aktorach. Kod przykładu JavaScriptu Dapr wygląda następująco:
To wyraźnie jest przestarzałe. Musiałem poświęcić dużo czasu, przekonując te trzy linie przez testową/przykładową eksplorację kodu Dapr
Przykłady kodu dla dostania/ustawiania stanu mają podobne problemy, więc stworzyłem dla nich problem na GitHubie.
Poza tymi drobnymi problemami, przygotowanie aktorów to bułka z masłem.
Ustawianie timerów i przypomnień dla mojego castingu też jest bardzo proste.
Stan
Bardzo łatwo udało mi się skonfigurować Dapr, aby trwał z Postgresem.
Zauważyłem też problemy ze skalowalnością w sposobie przechowywania przypomnień. Dapr przechowuje wszystkie alerty dla konkretnego typu uczestnika w jednej tablicy JSON. Co się stanie, jeśli ktoś ma mnóstwo przypomnień?
Inne wskazówki i wskazówki związane z Dapr
Zauważyłem podczas przeglądania kodu SDK JavaScript, że w kodzie praktycznie nie ma wielu komentarzy. To sprawia, że niemal niemożliwe jest coś wymyślić. Na przykład w metodzie addOrUpdateState menedżera stanu istnieje trzeci parametr zwany updateValueFactory. Jeśli w kodzie nie ma komentarzy, prawie niemożliwe jest określenie, na co polega callback.
Nie jestem też pewien, na ile podoba mi się komenda "dapr init" próbująca skonfigurować i uruchomić kontener redis. A co jeśli już mam pojemnik Redis? A co jeśli chcę użyć postgresa zamiast tego? Nie mogę znaleźć dokumentacji wyjaśniającej, jak zmienić funkcję dapr init.
Uwaga dla wszystkich, którzy mają problemy z używaniem pubsub. Musisz użyć "dapr run", aby obsługiwać zarówno wydawcę, jak i subskrybenta:
W przypadku aktorów i pubsubów warto pamiętać, że ważne jest, aby używać parametru --app-port, aby DAPR wiedział, na którym porcie działa twoja usługa. Wydarzenia pubsub i połączenia aktorów są wysyłane do Twojej usługi z Dapr sidecar przez połączenia http, więc musi wiedzieć, gdzie je wysyłać:
Przetestowałem mały samodzielnie hostowany "klaster" Dapr, uruchamiając moją instancję suba pubsub na dwóch różnych komputerach w mojej domowej sieci. Po prostu zadziałało!
Podsumowanie Dapr
Jeśli chcesz poznać więcej pomysłów na aplikacje rozproszone lub wirtualne aktory, polecam zacząć od Dapr. Orleans był pierwotnym pionierem, a Dapr to reboot, który wyniósł wszystko na wyższy poziom.
Oryginalny link:Logowanie do linku jest widoczne.
|