Asynchroniczność w ASP.NET - wprowadzenie
Asynchroniczność w ASP.NET to temat, który ostatnio przewija się gdzie nie spojrzę. Microsoftowy zespół od ASP.NET kilka miesięcy temu postanowił zatruć życie początkującym programistom tej platformy. Jak to się stało? Otóż w nowej wersji MVC usunęli starą bibliotekę do zarządzania uwierzytelnianiem i autoryzacją użytkowników. Co do samej zmiany nie będę się wdawał w szczegóły - jak wszystko, ma swoje dobre i złe strony. Istotne jest to, że szablon dla nowych aplikacji ASP.NET MVC 5 jest wypchany wywołaniami metod z końcówką Async. Większość tego postu odnosi się do wszystkich aplikacji internetowych, nie tylko ASP.NET, czy innych frameworków .NETowych.
Po co wielowątkowość w aplikacjach internetowych?
Aplikacje internetowe z natury muszą być wielowątkowe. Wyobraźmy sobie sytuację, gdzie do naszego serwera WWW przychodzą równocześnie sto żądań HTTP. Jeżeli nie rozdzielimy obliczeń:
- nie wykorzystujemy w pełni naszego procesora - po co 8 rdzeni na serwerze, skoro wszystkie obliczenia wykonujemy na jednym?
- prosimy się o atak odmowy dostępu - nasz system operacyjny nie będzie kolejkował żądań.
Oczywiście developerzy samej aplikacji nie muszą się tym zwykle przejmować. Umieszczając aplikację na serwerze WWW (IIS, Apache etc.) mamy ten problem z głowy. O co więc chodzi z tym wpisem? Kolejkowanie żądań czasem nie wystarczy.
Kiedy powinienem pisać asynchronicznie?
Zasadniczo, powody są trzy:
- wykonujesz operację na systemie plików (bazy danych też zwykle trzymane są na dysku),
- używasz zdalnego API (np. wrzucasz zdjęcia kotów na Facebooka),
- wykonujesz skomplikowane obliczenia, które można zrównoleglić.
Pierwsze dwa przypadki są do siebie podobne - oddajemy obliczenia do innego urządzenia (kontroler dysku, zdalny serwis). Co się wtedy dzieje z naszym wątkiem, w którym obsługujemy żądanie? Nasz wątek czeka. A mógłby robić inne rzeczy… :-)
Asynchroniczność to nie same zalety
Jak się możecie domyślać, wątki też kosztują. Zwykle serwery WWW mają dostępną pulę wątków, dzięki czemu nie musimy ich tworzyć i zabijać. Kosztem jest jednak przełączanie się pomiędzy wątkami, odpowiednia synchronizacja i przekazywanie danych.
Kolejna sprawa - klasyczne programowanie wielowątkowe jest trudne, musimy unikać zakleszczeń. W kolejnych wpisach pokażę, jak .NET 4.5 pozwala uniknąć tego problemu.
Na koniec zostaje perełka, a mianowicie: aplikacja musi być asynchroniczna “all the way”. Co to znaczy? Jeżeli napiszemy asynchroniczne repozytorium (np. do zapisywania danych do BD), to asynchroniczne musi być również wszystko, co wywołuje naszą metodę - serwis, kontroler, framework. W kolejnych wpisach przedstawię jak wygląda obecnie ASP.NET MVC i Entity Framework pod kątem asynchroniczności, a także jak możecie to wykorzystać.