Po zbadaniu koncepcji asynchronicznego tworzenia sieci, szczególnie ze źródła this, stworzyłem przykładową aplikację, aby udowodnić tę koncepcję.ASP.NET C# 5 Asynchroniczne aplikacje internetowe przy użyciu Async & Await
Rozwiązanie składa się z 2 aplikacji ASP.NET Web API. Pierwszy to symulowany powolny punkt końcowy; czeka na 1000 ms przed powrotem listę niestandardowej klasy o nazwie Student:
public IEnumerable<Student> Get()
{
Thread.Sleep(1000);
return new List<Student> { new Student { Name = @"Paul" }, new Student { Name = @"Steve" }, new Student { Name = @"Dave" }, new Student { Name = @"Sue" } };
}
Oto klasa Student:
public class Student
{
public string Name { get; set; }
}
Ten punkt końcowy jest obsługiwana w IIS 7 na localhost: 4002.
Drugi kontakty aplikacji pierwszym użyciu 2 punktów końcowych, jeden synchronicznych drugiej asynchronicznych:
public IEnumerable<Student> Get() {
var proxy = WebRequest.Create(@"http://localhost:4002/api/values");
var response = proxy.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
return JsonConvert.DeserializeObject<IEnumerable<Student>>(reader.ReadToEnd());
}
public async Task<IEnumerable<Student>> Get(int id) {
var proxy = new HttpClient();
var getStudents = proxy.GetStreamAsync(@"http://localhost:4002/api/values");
var stream = await getStudents;
var reader = new StreamReader(stream);
return JsonConvert.DeserializeObject<IEnumerable<Student>>(reader.ReadToEnd());
}
Jest obsługiwana w IIS 7 na localhost: 4001.
Oba punkty końcowe działają zgodnie z oczekiwaniami i wracają za około. 1 sekunda. Na podstawie wideo w powyższym linku o 13:25 metoda asynchroniczna powinna zwolnić wątek, minimalizując rywalizację.
Używam testów wydajności aplikacji przy użyciu Apache Bench. Oto czasy reakcji dla metody synchronicznej z 10 jednoczesnych żądań:
Jest to bardzo bym się spodziewać; więcej współbieżnych połączeń zwiększa rywalizację i wydłuża czas odpowiedzi. Jednak tutaj są asynchroniczne czasy reakcji:
Jak widać, nie wydaje się być jeszcze jakiś spór. Spodziewałbym się, że średni czas reakcji będzie bardziej zrównoważony. Jeśli uruchomię testy na obu punktach końcowych z 50 równoczesnymi żądaniami, nadal otrzymam podobne wyniki.
Na tej podstawie wydaje się, że zarówno metody asynchroniczne, jak i synchroniczne działają z mniej więcej taką samą szybkością (oczekiwaną), nie biorąc pod uwagę obciążenia metod asynchronicznych, ale także, że metoda asynchroniczna nie wydaje się zwalniaj wątki z powrotem do ThreadPool. Z zadowoleniem przyjmuję wszelkie uwagi lub wyjaśnienia, dziękuję.
Największą zmianą, jaką otrzymasz, jest metoda polegająca na użyciu zewnętrznych źródeł, takich jak baza danych. – JustAnotherUserYouMayKnow
Dzięki, pomyślałem, że tak było w przypadku długotrwałej prośby, którą właśnie symulowałem. Czy sugerujesz, że struktura asynchroniczna jest zoptymalizowana dla żądań opartych na IO, w przeciwieństwie do CPU-bound? Zmodyfikuję kod tak, aby zawierał żądanie bazy danych. –
Celem asynchronicznej struktury jest uwolnienie Nici, kiedy musi poczekać na odpowiedź, aby w międzyczasie mogła zająć się inną pracą. W większości przypadków dotyczy to żądań opartych na IO. Kiedy zażądasz dużo danych z bazy danych, co powinien nić tymczasem? Poczekaj, aż dane wrócą ... Albo wróć do wątku w międzyczasie i pracuj nad innymi, dopóki dane nie wrócą? – JustAnotherUserYouMayKnow