Marc Brooker, Ingenieur bei Amazon Web Services (AWS), hat Missverständnisse über die Effizienzsteigerung der Übertragung kleiner Nachrichten mit dem Nagle-Algorithmus, der standardmäßig im TCP/IP-Stack verwendet wird, aufgeklärt. Die Empfehlungen zielen darauf ab, den Nagle-Algorithmus standardmäßig zu deaktivieren, was im Kontext bestimmter Anwendungen durch das Setzen der TCP_NODELAY-Option für Netzwerksockets mittels des Aufrufs von setsockopt erreicht werden kann, wie es bereits in Projekten wie Node.js und curl seit langem praktiziert wird.
Der Nagle-Algorithmus ermöglicht die Aggregation kleiner Nachrichten zur Reduzierung des Datenverkehrs – er pausiert das Senden neuer TCP-Segmente, bis eine Bestätigung für den Empfang zuvor gesendeter Daten vorliegt. Beispielsweise werden bei der Übertragung von 1 Byte ohne Aggregation zusätzlich 40 Bytes mit TCP- und IP-Headern des Pakets gesendet. Unter modernen Bedingungen führt die Verwendung des Nagle-Algorithmus zu einer spürbaren Erhöhung der Latenz, die für interaktive und verteilte Anwendungen inakzeptabel ist.
Es gibt drei Hauptargumente für die standardmäßige Verwendung der TCP_NODELAY-Option, die den Nagle-Algorithmus deaktiviert:
- Inkompatibilität des Nagle-Algorithmus mit der Optimierung „delayed ACK“, bei der die ACK-Antwort nicht sofort, sondern erst nach Erhalt von Antwortdaten gesendet wird. Das Problem besteht darin, dass im Nagle-Algorithmus der Eingang eines ACK-Pakets ein Signal zum Senden aggregierter Daten ist, und wenn das ACK-Paket nicht eintrifft, erfolgt das Senden bei Ablauf eines Timeouts. Somit entsteht ein Teufelskreis, und das ACK-Paket funktioniert nicht als Signal, da die andere Seite die Daten aufgrund der Ansammlung auf der Senderseite nicht erhält, und der Sender sie nicht sendet, bevor der Timeout eintritt, da er kein ACK-Paket erhält.
- Der RFC für den Nagle-Algorithmus wurde 1984 angenommen und ist nicht auf die Parameter moderner Hochgeschwindigkeitsnetze angepasst und Server in Rechenzentren, was zu Problemen mit der Reaktionsfähigkeit führt. Die Verzögerung zwischen dem Senden einer Anfrage und dem Erhalten einer Antwort (RTT) in modernen Netzwerken beträgt 0,5 ms + einige Millisekunden beim Datenaustausch zwischen Rechenzentren in derselben Region + bis zu hundert Millisekunden beim globalen Versand. In diesen Millisekunden kann ein moderner Server eine enorme Menge an Arbeit verrichten.
- Moderne verteilte Anwendungen senden längst keine einzelnen Bytes mehr, und die Aggregation kleiner Daten wird normalerweise auf der Anwendungsebene realisiert. Selbst wenn die Größe der nützlichen Daten nur einige Bytes beträgt, steigt in der Regel die tatsächlich gesendete Informationsgröße erheblich an, nachdem die Serialisierung, die Verwendung von API-Wrappern in JSON und die Übertragung mit TLS-Verschlüsselung angewendet wurden. Eine Einsparung von 40 Byte wird weniger relevant.
Quelle: opennet.ru
