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.
futures-cpupool
jest to zalecane obejście brakuasync
wsparcia w Dieslu.