Czy usługa HttpClient jest bezpieczna w użyciu jednocześnie?

151

We wszystkich przykładach zastosowań, które mogę znaleźć HttpClient, jest używany do jednorazowych połączeń. Ale co w przypadku trwałej sytuacji klienta, w której można wysłać kilka żądań jednocześnie? Zasadniczo, czy można bezpiecznie wywoływać jednocześnie client.PostAsync2 wątki z tego samego wystąpienia HttpClient.

Nie szukam tutaj wyników eksperymentów. Przykładem roboczym może być po prostu fuks (i to uporczywy), a błędnym przykładem może być problem z błędną konfiguracją. Idealnie szukam autorytatywnej odpowiedzi na pytanie o obsługę współbieżności w HttpClient.

Alex K.
źródło
2
Przeczytaj również to pytanie, aby uzyskać więcej informacji na temat prawidłowego użytkowania HttpClienti usuwania: stackoverflow.com/questions/15705092/…
Mani Gandham

Odpowiedzi:

152

Według MSDN , od .NET 4.5 Poniższe metody instancji są bezpieczne wątkowo (dzięki @ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
Marcel N.
źródło
3
Tak, nie byłem tego pewien, ponieważ wydaje się, że jest to standardowe ostrzeżenie o wszystkim w MSDN (i pamiętam, że czytałem kilka blogów MSDN o tym, jak czasami to ostrzeżenie jest błędne, ponieważ jest stosowane na ślepo do wszystkiego).
Alex K
3
To jest źle; w sekcji uwag na stronie MSDN, do której utworzono łącze, jest napisane, że GetAsync, PostAsync itp. są bezpieczne wątkowo.
ischell,
4
@ischell: Mogę Państwa zapewnić, że tego akapitu nie było w momencie, gdy omawiano tę kwestię.
Marcel N.
7
Dlatego firma Microsoft zaprojektowała HttpClient do wielokrotnego użytku, ale klasa ma dane instancji dla nagłówków: client.DefaultRequestHeaders.Accept.Add (...);
cwills
8
Późno, ale chciałem skomentować @cwills. DefaultRequestHeaders to po prostu wartości domyślne. Jeśli potrzebujesz różnych nagłówków na podstawie żądania, możesz utworzyć nową StringContent (), ustawić dodatkowe nagłówki, a następnie użyć przeciążenia, które pobiera URI i HttpContent.
Ryan Anderson
92

Oto kolejny artykuł Henrika F. Nielsena na temat HttpClient, w którym mówi:

Domyślny HttpClient to najprostszy sposób, w jaki możesz rozpocząć wysyłanie żądań. Pojedynczy HttpClient może być używany do jednoczesnego wysyłania dowolnej liczby żądań HTTP, więc w wielu scenariuszach możesz po prostu utworzyć jednego HttpClient, a następnie użyć go do wszystkich swoich żądań.

mruczenie
źródło
13
A co, jeśli nazwa użytkownika i hasło mogą się zmieniać między wątkami? to jest to, o czym nie mogę znaleźć nikogo mówiącego
Nicholas DiPiazza
1
@NicholasDiPiazza: jak często to się zmienia? Jeśli istnieje znany zestaw par użytkownik / hasło, możesz utworzyć pulę wystąpień HttpClient.
Marcel N.
Tak, to właśnie skończyłem
Nicholas DiPiazza
2
Pamiętaj, że ponowne użycie tego samego HttpClient dla wszystkich żądań może spowodować przestarzałe problemy z DNS: github.com/dotnet/corefx/issues/11224 .
Ohad Schneider
1
@OhadSchneider Jeśli uważasz, że problem ogranicza się do .net core. Problem można rozwiązać za pomocą .net 4, wstrzykując niestandardowy HttpClientHandler do konstruktora HttpClient, a następnie ustawiając „ConnectionLeaseTimeout”. Jeśli jednak żadne żądania nie zostaną wysłane do punktu końcowego przez 100 sekund, połączenie zostanie odświeżone samodzielnie. chronione przesłonięcie Zadanie <HttpResponseMessage> SendAsync (żądanie HttpRequestMessage, CancellationToken cancellationToken) {var sp = ServicePointManager.FindServicePoint (request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
Timothy Gonzalez
17

Znaleziono jeden post na forum MSDN autorstwa Henrika F. Nielsena (jednego z głównych architektów HttpClient).

Szybkie podsumowanie:

  • Jeśli masz żądania, które są ze sobą powiązane (lub nie nadepną na siebie nawzajem), użycie tego samego HttpClient ma sens.
  • W ogóle zalecałbym ponowne użycie instancji HttpClient w jak największym stopniu.
Alex K.
źródło