Kiedy powinienem używać kontrolerów asynchronicznych w ASP.NET MVC?

Mam pewne obawy przy użyciu akcji asynchronicznych w ASP.NET MVC. Kiedy poprawia wydajność moich aplikacji, a kiedy nie?

  1. czy dobrze jest używać akcji asynchronicznej wszędzie w ASP.NET MVC?
  2. jeśli chodzi o metody oczekujące: czy powinienem używać słów kluczowych asynchronicznych/oczekujących, gdy chcę odpytywać bazę danych (poprzez EF/NHibernate/inny ORM)?
  3. Ile razy mogę użyć słów kluczowych oczekujących do asynchronicznie odpytywania bazy danych w One single action method?
Author: Steven Jeuris, 2015-06-01

6 answers

Metody asynchronicznej akcji są użyteczne, gdy akcja musi wykonać kilka niezależnych długich operacji.

Typowym zastosowaniem klasy AsyncController jest long-running Web połączenia serwisowe.

Czy moje wywołania do bazy danych powinny być asynchroniczne ?

Pula wątków usługi IIS może często obsługiwać o wiele więcej jednoczesnych żądań blokowania niż serwer bazy danych. Jeśli wąskim gardłem jest baza danych, asynchroniczne wywołania nie przyspieszą odpowiedzi bazy danych. Bez mechanizmu dławienia, wydajne wysyłanie większej ilości pracy do przytłoczonego serwera bazy danych za pomocą wywołań asynchronicznych tylko przenosi większe obciążenie do bazy danych. Jeśli DB jest wąskim gardłem, asynchroniczne wywołania nie będą magiczną kulą.

You should have a look at 1 oraz 2 referencje

Pochodzi z @PanagiotisKanavos Komentarze:

Ponadto async nie oznacza parallel. Wykonanie asynchroniczne zwalnia a cenna ThreadPool thread z blokowania dla zewnętrznego zasobu, dla brak złożoności i kosztów wydajności. Oznacza to, że ta sama maszyna IIS może obsługuj więcej jednoczesnych żądań, Nie żeby działały szybciej.

Należy również wziąć pod uwagę, że blokowanie połączeń zaczyna się od Spinwait obciążający procesor. W czasie stresu blokowanie połączeń będzie skutkować eskalacją opóźnień i recyklingiem puli aplikacji. Wywołania asynchroniczne po prostu unikaj tego

 90
Author: EnggForum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-14 02:24:03

Mój artykuł MSDN na ten temat może okazać się pomocny ; zająłem dużo miejsca w tym artykule opisując kiedy należy użyć async Na ASP.NET, nie tylko Jak używać async Na ASP.NET.

Mam pewne obawy przy użyciu akcji asynchronicznych w ASP.NET MVC. Kiedy to poprawia wydajność moich aplikacji, a kiedy-nie.

Najpierw zrozum, że async/await jest o uwolnienie wątków. W aplikacjach GUI chodzi głównie o uwolnienie wątku GUI , aby doświadczenie użytkownika było lepsze. Na aplikacjach serwerowych (w tym ASP.NET MVC), chodzi głównie o zwolnienie wątku żądania , aby serwer mógł skalować.

W szczególności, to nie będzie:

  • spraw, aby Twoje indywidualne prośby były realizowane szybciej. W rzeczywistości, będą one zakończyć (tylko trochę malutki) wolniej.
  • wróć do wywołującego / przeglądarki po naciśnięciu await. await tylko "daje" do ASP.NET Pula wątków, nie do przeglądarka.

Pierwsze pytanie brzmi - czy dobrze jest używać akcji asynchronicznej wszędzie w ASP.NET MVC?

Powiedziałbym, że dobrze jest używać go wszędzie tam, gdzie robisz I / O. może to niekoniecznie być korzystne , chociaż (patrz poniżej).

Jednak, to jest złe używać go do metod związanych z CPU. Czasami deweloperzy myślą, że mogą uzyskać korzyści z async poprzez wywołanie Task.Run w swoich kontrolerach, a to jest okropny pomysł. Bo ten kod kończy się uwolnienie wątku żądania poprzez podjęcie innego wątku, więc nie ma żadnych korzyści (a w rzeczywistości biorą karę za dodatkowe przełączniki wątku)!

Czy powinienem używać asynchronicznych / oczekujących słów kluczowych, gdy chcę odpytywać bazę danych (poprzez EF/NHibernate/inny ORM)?

Możesz użyć dowolnych dostępnych metod. W tej chwili większość głównych graczy obsługuje async, ale jest kilku, którzy tego nie robią. jeśli twój ORM nie obsługuje async, nie próbuj go owijać w Task.Run lub coś podobnego (patrz wyżej).

Zauważ, że powiedziałem "ty możesz używać". Jeśli mówisz o ASP.NET MVC z pojedynczym backendem bazy danych, to (prawie na pewno) nie uzyskasz żadnej korzyści skalowalności z async. Dzieje się tak dlatego, że usługi IIS mogą obsłużyć znacznie więcej jednoczesnych żądań niż pojedyncza instancja SQL server (lub inne klasyczne systemy RDBM). Jeśli jednak twój backend jest bardziej nowoczesny - klaster SQL server, Azure SQL, NoSQL itp. - i twój backend może skalować i Twoje wąskie gardło skalowalności to IIS, następnie możesz uzyskać korzyści skalowalności z async.

Trzecie pytanie - ile razy mogę użyć słów kluczowych oczekujących do asynchronicznie odpytywania bazy danych w jednej metodzie działania?

Ile chcesz. Należy jednak pamiętać, że wiele ORM ma regułę jednej operacji na połączenie. W szczególności, EF pozwala tylko na jedną operację dla DbContext; to prawda, czy operacja jest synchroniczna lub asynchroniczne.

Pamiętaj również o skalowalności backendu. Jeśli trafiasz na pojedynczą instancję SQL Server, a Twój IIS jest już w stanie utrzymać pełną wydajność SQLServer, podwajanie lub potrojenie presji na SQLServer w ogóle Ci nie pomoże.

 192
Author: Stephen Cleary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-26 14:09:41

Czy dobrze jest używać akcji asynchronicznej wszędzie w ASP.NET MVC?

Jak zwykle w programowaniu, to zależy. Zawsze jest kompromis, gdy idzie w dół pewną ścieżką.

async-await świeci w miejscach, w których wiesz, że będziesz otrzymywać jednocześnie żądania do swojej usługi i chcesz być w stanie skalować dobrze. Jak async-await pomaga w skalowaniu? W tym, że gdy wywołujesz asynchroniczne wywołanie IO synchronicznie , takie jak wywołanie sieciowe lub uderzając w twoją bazę danych, bieżący wątek, który jest odpowiedzialny za wykonanie, jest blokowany w oczekiwaniu na zakończenie żądania. Kiedy używasz async-await, włączasz framework do tworzenia maszyny stanowej dla ciebie, co zapewnia, że po zakończeniu wywołania IO, twoja metoda kontynuuje wykonywanie od miejsca, w którym została przerwana.

Należy zauważyć, że ta maszyna stanowa ma subtelny nad głową. Tworzenie metody asynchronicznej nie powoduje, że jest ona wykonywana szybciej , a to jest ważny czynnik aby zrozumieć i błędne przekonanie wielu ludzi.

Kolejną rzeczą, którą należy wziąć pod uwagę przy użyciu async-await, jest fakt, że jest to asynchroniczne przez całą drogę, co oznacza, że zobaczysz asynchroniczne przenikanie całego stosu połączeń, od góry do buttom. Oznacza to, że jeśli chcesz ujawnić synchroniczne API, często znajdziesz się w duplikacji pewnej ilości kodu, ponieważ async i sync nie mieszają się zbyt dobrze.

Czy powinienem używać asynchronicznych / oczekujących słów kluczowych, gdy chcesz odpytywać bazę danych (poprzez EF / NHibernate / inne ORM)?

Jeśli zdecydujesz się na użycie asynchronicznych wywołań IO, to tak, async-await będzie dobrym wyborem, ponieważ coraz nowocześniejsi dostawcy baz danych ujawniają metodę asynchroniczną implementującą TAP (Task Asynchronous Pattern).

Ile razy mogę użyć słów kluczowych oczekujących do zapytania bazy danych asynchronicznie w jednej metodzie działania?

Ile chcesz, o ile przestrzegasz zasad określonych przez dostawca baz danych. Nie ma limitu liczby połączeń asynchronicznych, które możesz wykonać. Jeśli masz zapytania, które są niezależne od siebie i mogą być wykonywane jednocześnie, możesz wykonać nowe zadanie dla każdego z nich i użyć await Task.WhenAll, aby poczekać na ukończenie obu zadań.

 18
Author: Yuval Itzchakov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-01 06:52:13

async akcje pomagają najlepiej, gdy akcje wykonują pewne operacje I \ O dla DB lub niektórych wywołań związanych z siecią, w których wątek przetwarzający żądanie zostanie zatrzymany, zanim otrzyma odpowiedź z wywołania związanego z DB lub siecią, które właśnie wywołałeś. Najlepiej używać wait z nimi i to naprawdę poprawi responsywność Twojej aplikacji (ponieważ mniej wątków ASP input\output zostanie zablokowanych podczas oczekiwania na DB lub inną operację tego typu). We wszystkich moich aplikacjach, gdy wiele wywołania do DB bardzo potrzebne zawsze zawijałem je w metodę await keyword.

 6
Author: Dimitri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-13 10:03:48

Moje 5 centów:

  1. Użyj async/await wtedy i tylko wtedy, gdy wykonujesz operację IO, taką jak DB lub zewnętrzna usługa webservice.
  2. zawsze preferuj asynchroniczne wywołania do DB.
  3. za każdym razem, gdy zapytasz DB.

P. S. istnieją wyjątkowe przypadki dla punktu 1, ale musisz mieć dobre zrozumienie asynchronicznych wewnętrznych do tego.

Dodatkową zaletą jest możliwość wykonania kilku połączeń IO równolegle w razie potrzeby:

Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result
 6
Author: bohdan_trotsenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-11 21:57:49

Jak wiesz, MVC obsługuje kontrolery asynchroniczne i powinieneś z tego skorzystać. Jeśli kontroler wykonuje długotrwałą operację (może to być dyskowe wejście / wyjście lub połączenie sieciowe z inną usługą zdalną), jeśli żądanie jest obsługiwane w sposób synchroniczny, wątek usługi IIS jest zajęty przez cały czas. W rezultacie wątek czeka tylko na zakończenie długiej operacji. Można go lepiej wykorzystać, obsługując inne żądania, podczas gdy operacja wymagana w pierwszym jest pod postęp. Pomoże to w obsłudze większej liczby jednoczesnych żądań. Twój webservice będzie wysoce skalowalny i nie będzie łatwo napotkać c10k problem . Dobrym pomysłem jest użycie async / wait for db queries. i tak, możesz ich używać tyle razy, ile uznasz za stosowne.

Spójrz tutaj dla doskonałych porad.

 2
Author: anurag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-08 22:03:31