Harken Sie auf dem Weg, um am Leben zu bleiben

Die Steigerung der Aktivität des Datenaustauschs zwischen Mikrodiensten ist häufig ein Problem in der Architektur moderner IT-Lösungen. Drücken Sie das Maximum und überleben Sie um jeden Preis - eine ernsthafte Herausforderung für jede Entwicklung. Daher ist die Suche nach optimalen Lösungen ein ununterbrochener Prozess. Der Artikel beschreibt kurz die Probleme, die bei der Verwendung hoch geladener http-Anforderungen auftreten können, und Möglichkeiten, diese zu umgehen.


Diese Geschichte beginnt mit einem Fehler. Irgendwie haben wir Lasttests durchgeführt, deren Hauptelement die Ausführung einer großen Anzahl kurzer http-Anfragen war. Ein Client, der unter Netcore 2.2 geschrieben wurde, löst ab einem bestimmten Zeitpunkt eine System.Net.Sockets.SocketException aus: Adresse, die bereits verwendet wird . Es wurde schnell klar, dass die Ports keine Zeit hatten, sich auf dem Client freizugeben, und irgendwann wurde dem System verweigert, einen neuen zu öffnen. Wenn wir nun zum Code gehen, bestand das Problem darin, den alten Ansatz mit der HttpWebRequest- Klasse und -Konstruktion zu verwenden:


var request = WebRequest.CreateHttp(uri);
using(var resp = request.GetResponse()){ … }

Es scheint, dass wir die Ressource freigeben, und der Port sollte rechtzeitig freigegeben werden. Allerdings netstat signalisiert einen raschen Anstieg der Zahl der Ports in TIME_WAIT Zustand. Dieser Status bedeutet, auf das Schließen der Verbindung zu warten (und möglicherweise verlorene Daten zu empfangen). Infolgedessen kann der Port 1-2 Minuten lang darin sein. Dieses Problem wird in vielen Artikeln ausführlich behandelt ( Probleme mit der Warteschlange TIME_WAIT , Verlauf über TIME_WAIT ). Dies bedeutet jedoch, dass dotnet „ehrlich“ versucht, die Verbindung zu schließen, und dies geschieht bereits durch den Fehler der Timeout-Einstellungen im System.


Warum passiert das und wie geht man damit um?


keep-alive. . , . msdn, KeepAlive HttpWebRequest true. HttpWebRequest «» , , . , HttpWebRequest «Connection: keep-alive», HTTP/1.1. , , KeepAlive. HttpWebRequest.KeepAlive = false, «Connection: close». , . nginx .


:


while (true)
{
  var request = WebRequest.CreateHttp(uri);
  request.KeepAlive = false;
  var resp = await request.GetResponseAsync();
  using (var sr = new StreamReader(resp.GetResponseStream()))
  {
    var content = sr.ReadToEnd();
  }
}

, ( 1000 ) . CLOSE_WAIT, LAST_ACK. - , . , «» .


,


, , . keep-alive HttpClient. .


, , ? keep-alive nginx:


  • keepalive_timeout – ( 15)
  • keepalive_requests – ( 100)

netstat wireshark, . keepalive_requests (> 1000) , .



http , . . , , keep-alive. keep-alive , .


:


  • RunHttpClient – HttpClient "Connection: keep-alive"
  • RunHttpClientClosed – HttpClient "Connection: closed"
  • RunWebRequestClosed - verwendet den Klassen-HttpWebRequest-Modus "Verbindung: geschlossen"

Der Nginx-Server wird mit den folgenden Parametern konfiguriert:


  • keepalive_timeout 60s;
  • keepalive_requests 100000;

MethodeN.Die WerbungenBedeuten
Runhttpclient10001963,3 ms
RunWebRequestClosed100013,857,4 ms
RunHttpClientClosed100011.612,4 ms
Runhttpclient10.00019.573,9 ms
RunWebRequestClosed10.000137.947,4 ms
RunHttpClientClosed10.000116.112,9 ms

All Articles