Czy diesel powinien być uruchamiany przy użyciu aktora synchronizacji, actix_web :: web :: block czy futures-cpupool?


10

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::blockdo 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.


Z komentarzy w tym wydaniu wynika, że futures-cpupooljest to zalecane obejście braku asyncwsparcia w Dieslu.
Jmb

To jest bardziej ogólne rozwiązanie. Mam nadzieję na coś, co wykorzysta system Actix. Niemniej jednak zajmę się teraz futures-cpupool, aby szukać problemów.
logina,

Witamy w Stack Overflow! Wygląda na to, że na twoje pytanie mogą odpowiedzieć odpowiedzi: jakie jest najlepsze podejście do enkapsulacji blokujących I / O w przyszłości? . Jeśli nie, edytuj swoje pytanie, aby wyjaśnić różnice. W przeciwnym razie możemy oznaczyć to pytanie jako już udzielone.
Shepmaster,

Ponieważ cpupool współdziała również z pulą blokujących połączeń w r2d2, nie jestem pewien, jak najlepiej to rozwiązać. Teraz sam się nad tym zastanawiam i wkrótce to zaktualizuję.
logina,

Odpowiedzi:


3

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.


6
czytając moje ustalenia powyżej - proszę podać w odpowiedzi informacje , a nie pytanie.
Shepmaster
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.