tło
Pracuję nad aplikacją webową actix używającą oleju napędowego przez R2D2 i nie jestem pewien, jak najlepiej wykonać zapytania asynchroniczne. Znalazłem trzy opcje, które wydają się rozsądne, ale nie jestem pewien, która z nich jest najlepsza.
Potencjalne rozwiązania
Synchronizuj aktora
Na przykład mógłbym skorzystać z przykładu actix , ale jest to dość skomplikowane i wymaga sporej ilości płyty kotłowej do zbudowania. Mam nadzieję, że istnieje bardziej rozsądne rozwiązanie.
Actix_web::web::block
Jako kolejną opcję mógłbym użyć tej funkcji actix_web::web::block
do zawijania moich funkcji zapytania w przyszłość, ale nie jestem pewien, jakie będą tego konsekwencje dla wydajności.
Czy zapytanie działa wtedy w tym samym systemie Tokio? Z tego, co mogłem znaleźć w źródle, tworzy on wątek w podstawowej puli wątków actix-web . Czy to problem?
Jeśli dobrze przeczytam kod, r2d2 blokuje jego wątek podczas uzyskiwania połączenia, co blokowałoby część podstawowej puli actix-web. To samo dotyczy zapytań do bazy danych. Czy to zablokowałoby cały actix-web, jeśli wykonam więcej zapytań niż mam wątki w tej puli? Jeśli tak, duży problem.
Futures-cpupool
Wreszcie, bezpiecznym zakładem, który może mieć pewne niepotrzebne koszty ogólne, jest futures-cpupool . Główny problem polega na tym, że oznacza to dodanie kolejnej skrzynki do mojego projektu, chociaż nie podoba mi się pomysł, że wiele puli procesorów unosi się w mojej aplikacji bez potrzeby.
Ponieważ zarówno r2d2, jak i diesel będą blokować, jest tutaj zaskakująca ilość podstępnych rzeczy.
Co najważniejsze, nie współużytkuj tego cpupool z niczym, co nie korzysta z tej samej puli r2d2 (ponieważ wszystkie utworzone wątki mogą po prostu blokować oczekiwanie na połączenie r2d2, blokując całą pulę, gdy istnieje praca).
Po drugie (nieco bardziej oczywiste), dlatego nie powinieneś mieć więcej połączeń r2d2 niż wątków w puli i odwrotnie, ponieważ większe zmarnowałoby zasoby (połączenia nieużywane / wątki ciągle blokowane) (być może jeszcze jeden wątek, być może szybciej przekazywanie połączenia przez program planujący OS, a nie program planujący cpupool).
Na koniec pamiętaj, jakiej bazy danych używasz i jaką wydajność tam masz. Uruchamianie pojedynczego połączenia r2d2 i pojedynczego wątku w puli może być najlepsze w przypadku aplikacji do zapisu z dużym obciążeniem sqlite (chociaż polecam dla tego odpowiednią bazę danych).
Stare odpowiedzi
Stare rozwiązania, które mogą działać
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
Zasadniczo zaleca Futures-cpupool.
Jakie jest najlepsze podejście do enkapsulacji blokujących We / Wy w przyszłości?
Poleca Futures-cpupool w ogólnych przypadkach.
Stare rozwiązania, które nie działają
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
Naprawdę fajna poprawka dla starej wersji Actix-web. Z tego, co mogę znaleźć, żądania nie zawierają już puli procesorów.
źródło
futures-cpupool
jest to zalecane obejście brakuasync
wsparcia w Dieslu.Odpowiedzi:
Idę z futures-cpupool. To najlepsze rozwiązanie ze względu na blokujący charakter moich interakcji.
Używanie actix_web :: web :: block jest wystarczająco przyzwoite, ale użyje współużytkowanej puli wątków w actix (i ze względu na wywołania blokujące używam tego może zablokować całą pulę wątków i zakłócać inne zadania powierzone actix_web).
Lepiej jest użyć futures-cpupool do utworzenia osobnej puli wątków dla bazy danych tylko dla interakcji z bazą danych. W ten sposób grupujesz wszystkie zadania, które muszą na siebie czekać (gdy jest więcej zadań niż połączeń) w jedną pulę, zapobiegając blokowaniu przez nie innych zadań, które nie wymagają połączenia i potencjalnie ograniczając liczbę wątków do liczba połączeń (aby zadanie zostało zaplanowane tylko wtedy, gdy nie zostanie zablokowane).
W przypadku, gdy chcesz użyć tylko jednego połączenia z bazą danych (lub bardzo niewielu), aktor synchronizacji jest całkiem dobrą opcją. Będzie działał jak futures-cpupool z jednym wątkiem, zapewniając, że wszystkie zadania są uruchamiane pojedynczo, z tym wyjątkiem, że użyje jednego z podstawowych wątków actix-web zamiast osobnego (dlatego jest dobry tylko dla bardzo niewielu połączeń) . Uważam jednak, że płyta kotła jest zbyt duża, aby była tego warta.
źródło