QUIC in Aktion: Wie Uber es implementiert hat, um die Leistung zu optimieren

Das QUIC-Protokoll ist äußerst interessant anzusehen, daher schreiben wir gerne darüber. Wenn die vorherigen Veröffentlichungen zu QUIC jedoch eher historischer Natur (Material, wenn Sie möchten) und Material waren, freuen wir uns, heute eine andere Interpretation zu veröffentlichen - wir werden über die tatsächliche Anwendung des Protokolls im Jahr 2019 sprechen. Und es geht nicht um eine kleine Infrastruktur in einer bedingten Garage, sondern um Uber, das fast auf der ganzen Welt funktioniert. Wie kamen die Ingenieure des Unternehmens zu der Entscheidung, QUIC in der Produktion einzusetzen, wie testeten sie und was sahen sie nach dem Start in die Produktion - unter dem Schnitt.
Bilder sind anklickbar. Viel Spaß beim Lesen!



Uber ist ein globaler Maßstab, nämlich 600 Präsenzstädte, in denen die Anwendung vollständig auf dem drahtlosen Internet von mehr als 4.500 Mobilfunkbetreibern basiert. Benutzer erwarten, dass die Anwendung nicht nur schnell, sondern auch in Echtzeit funktioniert. Um dies sicherzustellen, benötigt die Uber-Anwendung eine geringe Latenz und eine sehr zuverlässige Verbindung. Leider fühlt sich der HTTP / 2- Stack in dynamischen und verlustanfälligen drahtlosen Netzwerken nicht gut an. Wir haben festgestellt, dass in diesem Fall eine geringe Leistung in direktem Zusammenhang mit TCP-Implementierungen in den Kerneln von Betriebssystemen steht.

Um das Problem zu lösen, haben wir QUIC angewendet, ein modernes Protokoll mit Kanalmultiplex , mit dem wir die Leistung des Transportprotokolls besser kontrollieren können. Die IETF- Arbeitsgruppe standardisiert derzeit QUIC als HTTP / 3 .

Nach detaillierten Tests kamen wir zu dem Schluss, dass die Implementierung von QUIC in unserer Anwendung die Verzögerungen im Vergleich zu TCP verringert. Am Beispiel von Fahrer- und Beifahreranwendungen beobachteten wir einen Rückgang des Bereichs von 10 bis 30% für den HTTPS-Verkehr. QUIC gab uns auch die End-to-End-Kontrolle über benutzerdefinierte Pakete.

In diesem Artikel teilen wir unsere Erfahrungen mit der Optimierung von TCP für Uber-Anwendungen mithilfe eines Stacks, der QUIC unterstützt.

Letztes Wort der Technologie: TCP


Heute ist TCP das am häufigsten verwendete Transportprotokoll für die Bereitstellung von HTTPS-Verkehr im Internet. TCP stellt einen zuverlässigen Bytestrom bereit und bewältigt so die Überlastung des Netzwerks und den Verlust der Verbindungsschicht. Die weit verbreitete Verwendung von TCP für den HTTPS-Verkehr erklärt sich aus der Allgegenwart des ersteren (fast jedes Betriebssystem enthält TCP), der Verfügbarkeit auf dem größten Teil der Infrastruktur (z. B. auf Load Balancern, HTTPS-Proxys und CDNs) und der sofort einsatzbereiten Funktionalität, die auf den meisten Plattformen und Plattformen verfügbar ist Netzwerke.

Die meisten Benutzer verwenden unsere Anwendung unterwegs, und TCP-Verzögerungen sind weit entfernt von den Echtzeitanforderungen unseres HTTPS-Verkehrs. Einfach ausgedrückt, Benutzer auf der ganzen Welt sind damit konfrontiert - Abbildung 1 zeigt Verzögerungen in Großstädten:


Abbildung 1. Das Ausmaß der Verzögerungen variiert in den Hauptstädten, in denen Uber tätig ist.

Trotz der Tatsache, dass es in indischen und brasilianischen Netzen mehr Verzögerungen gab als in den USA und Großbritannien, sind die Verzögerungen im Heck viel größer als die durchschnittlichen Verzögerungen. Dies gilt auch für die USA und Großbritannien.

TCP-Leistung über Funk


TCP wurde für kabelgebundene Netzwerke entwickelt, dh mit Schwerpunkt auf gut vorhersehbaren Verbindungen. Drahtlose Netzwerke haben jedoch ihre eigenen Eigenschaften und Schwierigkeiten. Erstens sind drahtlose Netzwerke aufgrund von Interferenzen und Signaldämpfung verlustanfällig. Beispielsweise reagieren Wi-Fi-Netzwerke empfindlich auf Mikrowellen, Bluetooth und andere Funkwellen. Mobilfunknetze leiden unter Signalverlust ( Pfadverlust ) aufgrund von Reflexion / Absorption des Signals durch Objekte und Gebäude sowie Störungen durch benachbarte Zelltürme . Dies führt zu signifikanteren (4-10-fachen) und einer Vielzahl von Round-Trip-Verzögerungen (RTT) und Paketverlusten im Vergleich zu einer Kabelverbindung.

Um Bandbreitenschwankungen und -verlusten entgegenzuwirken, verwenden Mobilfunknetze normalerweise große Puffer für Verkehrsstöße. Dies kann zu einer übermäßigen Priorität führen, was längere Verzögerungen bedeutet. Sehr oft behandelt TCP eine solche Sequenz als Verlust aufgrund eines erhöhten Zeitlimits, so dass TCP dazu neigt, ein Relais durchzuführen und dadurch den Puffer zu füllen. Dieses Problem ist als Bufferbloat ( übermäßige Netzwerkpufferung, Pufferschwellung ) bekannt und ein sehr ernstes Problem des modernen Internets.

Schließlich variiert die Leistung des Mobilfunknetzes je nach Netzbetreiber, Region und Zeit. In Abbildung 2 haben wir die mittleren Verzögerungen des HTTPS-Verkehrs über Zellen in einer Reichweite von 2 Kilometern erfasst. Daten werden für die beiden größten Mobilfunkbetreiber in Delhi, Indien, gesammelt. Wie Sie sehen können, variiert die Leistung von Zelle zu Zelle. Außerdem unterscheidet sich die Leistung eines Bedieners von der Leistung des zweiten. Dies wird durch Faktoren wie Muster des Netzwerkzugriffs unter Berücksichtigung von Zeit und Ort, Benutzermobilität sowie Netzwerkinfrastruktur unter Berücksichtigung der Dichte der Türme und des Verhältnisses der Netzwerktypen (LTE, 3G usw.) beeinflusst.


Abbildung 2. Verzögerungen für ein Beispiel eines Radius von 2 km. Delhi, Indien.

Auch die Leistung von Mobilfunknetzen variiert im Laufe der Zeit. Abbildung 3 zeigt die mittlere Verzögerung nach Wochentag. Wir haben auch einen Unterschied in kleinerem Maßstab beobachtet - innerhalb eines Tages und einer Stunde.


Abbildung 3. Schwanzverzögerungen können an verschiedenen Tagen erheblich variieren, jedoch mit demselben Bediener.

All dies führt dazu, dass die TCP-Leistung in drahtlosen Netzwerken ineffizient ist. Bevor wir jedoch nach Alternativen zu TCP suchten, wollten wir ein genaues Verständnis der folgenden Punkte entwickeln:
  • Ist TCP der Hauptverursacher von Verzögerungen bei unseren Anwendungen?
  • Haben moderne Netze erhebliche und unterschiedliche Round-Trip-Verzögerungen (RTT)?
  • Welche Auswirkungen hat der Leistungsverlust von RTT und TCP?

TCP-Leistungsanalyse


Um zu verstehen, wie wir die TCP-Leistung analysiert haben, erinnern wir uns kurz daran, wie TCP Daten von einem Absender zu einem Empfänger überträgt. Zunächst stellt der Absender eine TCP-Verbindung her, indem er einen Drei-Wege- Handshake ausführt: Der Absender sendet ein SYN-Paket, wartet auf ein SYN-ACK-Paket vom Empfänger und sendet dann ein ACK-Paket. Zusätzliche zweite und dritte Durchgänge dienen zum Erstellen einer TCP-Verbindung. Der Empfänger bestätigt den Empfang jedes Pakets (ACK), um eine zuverlässige Zustellung sicherzustellen.

Wenn ein Paket oder eine ACK verloren geht, sendet der Absender nach einer Zeitüberschreitung erneut (RTO, Zeitüberschreitung bei erneuter Übertragung ). Die RTO wird dynamisch basierend auf verschiedenen Faktoren berechnet, beispielsweise der erwarteten RTT-Verzögerung zwischen Sender und Empfänger.


Abbildung 4. Der TCP / TLS-Paketaustausch enthält einen Mechanismus zur erneuten Übertragung.

Um festzustellen, wie TCP in unseren Anwendungen funktioniert, haben wir eine Woche lang TCP-Pakete mit tcpdump auf den Kampfverkehr von indischen Grenzservern überwacht. Dann haben wir die TCP-Verbindungen mit tcptrace analysiert. Darüber hinaus haben wir eine Android-Anwendung erstellt, die emulierten Datenverkehr an einen Testserver sendet und den tatsächlichen Datenverkehr so ​​weit wie möglich nachahmt. Smartphones mit dieser Anwendung wurden an mehrere Mitarbeiter verteilt, die mehrere Tage lang Protokolle sammelten.

Die Ergebnisse beider Experimente stimmten überein. Wir haben hohe RTT-Verzögerungen gesehen; Schwanzwerte waren fast 6-mal höher als der Medianwert; arithmetischer Mittelwert der Verzögerungen - mehr als 1 Sekunde. Viele Verbindungen waren verlustbehaftet, sodass TCP 3,5% aller Pakete erneut übertrug. In überlasteten Gebieten wie Flughäfen und Bahnhöfen verzeichneten wir einen Verlust von 7%. Solche Ergebnisse werfen Zweifel an der herkömmlichen Weisheit auf, dass die in Mobilfunknetzen verwendeten fortschrittlichen Neuübertragungsschemata den Transportverlust erheblich reduzieren. Nachfolgend finden Sie die Testergebnisse der Anwendung „Simulator“:
NetzwerkmetrikenWerte
RTT, Millisekunden [50%, 75%, 95%, 99%][350, 425, 725, 2300]
RTT-Diskrepanz, Sekunden~ 1,2 s Durchschnitt
Paketverlust bei instabilen VerbindungenIm Durchschnitt ~ 3,5% (7% in Gebieten mit Überlastung)

Fast die Hälfte dieser Verbindungen hatte mindestens einen Paketverlust, von denen die meisten SYN- und SYN-ACK-Pakete waren. Die meisten TCP-Implementierungen verwenden einen RTO-Wert von 1 Sekunde für SYN-Pakete, der für nachfolgende Verluste exponentiell ansteigt. Die Ladezeit der Anwendung kann sich erhöhen, da TCP mehr Zeit zum Herstellen von Verbindungen benötigt.

Im Fall von Datenpaketen reduzieren hohe RTOs die nützliche Netzwerkauslastung bei vorübergehenden Verlusten in drahtlosen Netzwerken erheblich. Wir haben festgestellt, dass die durchschnittliche Neuübertragungszeit etwa 1 Sekunde mit einer Endverzögerung von fast 30 Sekunden beträgt. Solche hohen Verzögerungen auf TCP-Ebene verursachten HTTPS-Timeouts und Wiederholungsversuche, was die Latenz und die Ineffizienz des Netzwerks weiter erhöhte.

Während das 75. Perzentil der gemessenen RTT etwa 425 ms betrug, betrug das 75. Perzentil für TCP fast 3 Sekunden. Dies deutet darauf hin, dass der Verlust TCP gezwungen hat, 7 bis 10 Durchgänge durchzuführen, um Daten erfolgreich zu übertragen. Dies kann auf eine ineffektive RTO-Berechnung, die Unfähigkeit von TCP, schnell auf den Verlust der letzten Pakete im Fenster zu reagieren, und die Ineffizienz des Überlastungssteuerungsalgorithmus zurückzuführen sein, der nicht zwischen drahtlosen Verlusten und Verlusten aufgrund von Netzwerküberlastung unterscheidet. Nachfolgend sind die Ergebnisse des TCP-Verlusttests aufgeführt:
TCP-PaketverluststatistikWert
Prozentsatz der Verbindungen mit mindestens 1 Paketverlust45%
Der Prozentsatz der Verbindungen mit Verlust während des Verbindungsaufbaus30%
Der Prozentsatz der Verbindungen mit Verlust während des Datenaustauschs76%
Verteilung der Verzögerungen bei erneuter Übertragung, Sekunden [50%, 75%, 95%, 99%][1, 2,8, 15, 28]
Verteilung von Neuübertragungen für ein einzelnes Paket oder TCP-Segment[1,3,6,7]

QUIC-Anwendung


QUIC wurde ursprünglich von Google entwickelt und ist ein modernes Multithread-Transportprotokoll, das auf UDP ausgeführt wird. Im Moment befindet sich QUIC im Standardisierungsprozess (wir haben bereits geschrieben, dass es sozusagen zwei Versionen von QUIC gibt, die Neugierigen können dem Link folgen - ca. Übersetzer). Wie in Abbildung 5 gezeigt, wird QUIC unter HTTP / 3 gehostet (tatsächlich HTTP / 2 über QUIC - dies ist HTTP / 3, das jetzt stark standardisiert ist). Es ersetzt teilweise die HTTPS- und TCP-Schichten und verwendet UDP, um Pakete zu bilden. QUIC unterstützt nur die sichere Datenübertragung, da TLS vollständig in QUIC integriert ist.


Abbildung 5: QUIC funktioniert unter HTTP / 3 und ersetzt TLS, das früher unter HTTP / 2 funktioniert hat.

Nachfolgend sind die Gründe aufgeführt, die uns überzeugt haben, QUIC zur Stärkung von TCP zu verwenden:
  • 0-RTT-Verbindungsaufbau. QUIC ermöglicht die Wiederverwendung von Berechtigungen aus früheren Verbindungen, wodurch die Anzahl der Sicherheitshandshakes verringert wird. In Zukunft wird TLS1.3 0-RTT unterstützen, es ist jedoch weiterhin ein Drei-Wege-TCP-Handshake erforderlich.
  • Überwindung der HoL-Blockierung. HTTP / 2 verwendet eine TCP-Verbindung für jeden Client, um die Leistung zu verbessern. Dies kann jedoch zu einem HoL-Block (Head-of-Line) führen. QUIC vereinfacht das Multiplexen und liefert Anforderungen unabhängig voneinander an die Anwendung.
  • Überlastungsmanagement. QUIC befindet sich auf Anwendungsebene, wodurch es einfacher wird, den Haupttransportalgorithmus zu aktualisieren, der das Senden basierend auf Netzwerkparametern (Verlustbetrag oder RTT) steuert. Die meisten TCP-Implementierungen verwenden den CUBIC- Algorithmus, der für verzögerungsempfindlichen Datenverkehr nicht optimal ist. Neu entwickelte Algorithmen wie BBR modellieren das Netzwerk genauer und optimieren die Latenz. Mit QUIC können Sie BBR verwenden und diesen Algorithmus aktualisieren, wenn er verbessert wird .
  • Verluste ausgleichen. QUIC ruft zwei TLPs ( Tail Loss Probe ) auf, bevor die RTO ausgelöst wird - auch wenn die Verluste sehr spürbar sind. Dies unterscheidet sich von TCP-Implementierungen. TLP überträgt hauptsächlich das letzte Paket (oder ein neues, falls vorhanden) erneut, um eine schnelle Wiederauffüllung auszulösen. Die Schwanzverzögerungsverarbeitung ist besonders nützlich für die Arbeitsweise von Uber mit dem Netzwerk, insbesondere für kurze, episodische und verzögerungsempfindliche Datenübertragungen.
  • optimiertes ACK. Da jedes Paket eine eindeutige Seriennummer hat, besteht kein Problem bei der Unterscheidung zwischen Paketen, wenn diese weitergeleitet werden. ACK-Pakete enthalten auch Zeit zum Verarbeiten des Pakets und zum Generieren clientseitiger ACKs. Diese Funktionen stellen sicher, dass QUIC die RTT genauer berechnet. Das QUIC ACK unterstützt bis zu 256 NACK- Bereiche, wodurch der Absender widerstandsfähiger gegen Paketaustausch ist und dabei weniger Bytes verwendet. Selective ACK ( SACK ) in TCP löst dieses Problem nicht in allen Fällen.
  • Verbindungsmigration. QUIC-Verbindungen werden durch eine 64-Bit-ID identifiziert. Wenn der Client die IP-Adressen ändert, können Sie die ID der alten Verbindung ohne Unterbrechung weiterhin für die neue IP-Adresse verwenden. Dies ist eine sehr gängige Praxis für mobile Anwendungen, wenn ein Benutzer zwischen Wi-Fi und Mobilfunkverbindungen wechselt.

Alternativen zu QUIC


Wir haben uns alternative Lösungsansätze angesehen, bevor wir uns für QUIC entschieden haben.

Zunächst haben wir versucht, TPC-PoPs (Points of Presence) bereitzustellen, um TCP-Verbindungen näher an den Benutzern herzustellen. Im Wesentlichen beenden PoPs die TCP-Verbindung mit dem mobilen Gerät näher am Mobilfunknetz und leiten den Datenverkehr an die ursprüngliche Infrastruktur weiter. Wenn wir TCP näher schließen, können wir möglicherweise die RTT reduzieren und sicherstellen, dass TCP besser auf dynamische drahtlose Umgebungen reagiert. Unsere Experimente haben jedoch gezeigt, dass RTT und Verluste größtenteils aus zellularen Netzwerken stammen und die Verwendung von PoPs keine signifikante Leistungsverbesserung bietet.

Wir haben uns auch mit der Optimierung der TCP-Parameter befasst. Die Konfiguration des TCP-Stacks auf unseren heterogenen Edgeservern war schwierig, da TCP in verschiedenen Betriebssystemversionen unterschiedliche Implementierungen aufweist. Es war schwierig, dies zu implementieren und verschiedene Netzwerkkonfigurationen zu testen. Die Konfiguration von TCP direkt auf Mobilgeräten war aufgrund mangelnder Berechtigung nicht möglich. Noch wichtiger ist, dass Chips wie Verbindungen mit 0-RTT und eine verbesserte RTT-Vorhersage für die Protokollarchitektur von entscheidender Bedeutung sind. Daher ist es nicht möglich, allein durch die Konfiguration von TCP signifikante Vorteile zu erzielen.

Schließlich haben wir mehrere UDP-basierte Protokolle evaluiert, mit denen das Video-Streaming behoben werden kann. Wir wollten wissen, ob diese Protokolle in unserem Fall hilfreich sind. Leider fehlten ihnen viele Sicherheitseinstellungen und sie benötigten eine zusätzliche TCP-Verbindung für Metadaten und Steuerinformationen.

Unsere Untersuchungen haben gezeigt, dass QUIC fast das einzige Protokoll ist, das bei dem Problem des Internetverkehrs helfen kann, wobei sowohl Sicherheit als auch Leistung berücksichtigt werden.

QUIC-Integration in die Plattform


Um QUIC erfolgreich zu integrieren und die Anwendungsleistung unter schlechten Kommunikationsbedingungen zu verbessern, haben wir den alten Stack (HTTP / 2 über TLS / TCP) durch das QUIC-Protokoll ersetzt. Wir haben die Cronet- Netzwerkbibliothek von Chromium Projects verwendet , die die ursprüngliche Google-Version des Protokolls - gQUIC - enthält. Diese Implementierung wird auch ständig verbessert, um der neuesten IETF-Spezifikation zu entsprechen.

Zuerst haben wir Cronet in unsere Android-Apps integriert, um QUIC-Unterstützung hinzuzufügen. Die Integration wurde durchgeführt, um die Migrationskosten zu minimieren. Anstatt den alten Netzwerkstapel, der die OkHttp- Bibliothek verwendete, vollständig zu ersetzen, haben wir Cronet UNTER das OkHttp-API-Framework integriert. Durch diese Integration haben wir Änderungen in unseren Netzwerkaufrufen (die von Retrofit verwendet werden) auf API-Ebene vermieden.

Ähnlich wie bei Android-Geräten haben wir Cronet in Uber-Anwendungen für iOS implementiert und den HTTP-Verkehr von Netzwerk- APIs mithilfe von NSURLProtocol abgefangen . Diese von der iOS Foundation bereitgestellte Abstraktion verarbeitet protokollspezifische URL-Daten und stellt sicher, dass wir Cronet ohne erhebliche Migrationskosten in unsere iOS-Apps integrieren können.

Quic auf Google Cloud Balancers abgeschlossen


Auf der Backend-Seite wird die QUIC-Beendigung von der Google Cloud Load Balancing-Infrastruktur bereitgestellt, die Alt-SVC- Header in Antworten verwendet, um QUIC zu unterstützen. Im Allgemeinen fügt der Balancer jeder HTTP-Anforderung den alt-svc-Header hinzu und überprüft bereits die QUIC-Unterstützung für die Domäne. Wenn der Cronet-Client eine HTTP-Antwort mit diesem Header empfängt, verwendet er QUIC für nachfolgende HTTP-Anforderungen an diese Domäne. Sobald der Balancer QUIC abgeschlossen hat, sendet unsere Infrastruktur diese Aktion explizit über HTTP2 / TCP an unsere Rechenzentren.

Leistung: Ergebnisse


Hervorragende Leistung ist der Hauptgrund für unsere Suche nach einem besseren Protokoll. Zuerst haben wir einen Stand mit Netzwerkemulation erstellt, um herauszufinden, wie sich QUIC mit verschiedenen Netzwerkprofilen verhält. Um den Betrieb von QUIC in realen Netzwerken zu testen, haben wir in Neu-Delhi mit emuliertem Netzwerkverkehr experimentiert, der HTTP-Anrufen in der Passagieranwendung sehr ähnlich ist.

Versuch 1


Inventar für Experimente:
  • Android-Testgeräte mit OkHttp- und Cronet-Stacks, um sicherzustellen, dass HTTPS-Datenverkehr über TCP bzw. QUIC gesendet wird;
  • ein Java-basierter Emulationsserver, der in Antworten denselben Typ von HTTPS-Headern sendet und Clientgeräte lädt, um Anforderungen von ihnen zu empfangen;
  • Cloud-Proxys, die sich physisch in der Nähe von Indien befinden, um TCP- und QUIC-Verbindungen herzustellen. Während wir den Reverse-Proxy unter NGINX verwendet haben , um TCP abzuschließen, war es schwierig, den Open-Source-Reverse-Proxy für QUIC zu finden. Wir haben den Reverse-Proxy für QUIC selbst erstellt, indem wir den Basis-QUIC-Stack von Chromium verwendet und ihn als Open Source in Chrom veröffentlicht haben.


Abbildung 6. Der Reisesatz für TCP- und QUIC-Tests bestand aus Android-Geräten mit OkHttp und Cronet, Cloud-Proxys zum Beenden von Verbindungen und einem Emulationsserver.

Experiment 2


Als Google QUIC mithilfe von Google Cloud Load Balancing zur Verfügung stellte , verwendeten wir dasselbe Inventar, jedoch mit einer Änderung: Anstelle von NGINX verwendeten wir Google Balancer, um TCP- und QUIC-Verbindungen von Geräten herzustellen und den HTTPS-Verkehr zum Emulationsserver weiterzuleiten . Balancer sind auf der ganzen Welt verteilt, verwenden jedoch den PoP-Server, der dem Gerät am nächsten liegt (dank der Geolokalisierung).


Abbildung 7. Im zweiten Experiment wollten wir die TCP-Abschlussverzögerung und QUIC vergleichen: Verwenden von Google Cloud und Verwenden unseres Cloud-Proxys.

Infolgedessen erwarteten uns mehrere Enthüllungen:
  • Die PoP-Terminierung verbesserte die TCP-Leistung. Da Balancer die TCP-Verbindung näher an den Benutzern herstellen und perfekt optimiert sind, führt dies zu einer geringeren RTT, was die TCP-Leistung verbessert. QUIC , TCP ( 10-30 ).
  • (hops) . QUIC- ( 50 ), , – 15%- 20%- 99 TCP. , – (bottleneck) .


8. , QUIC TCP.


, QUIC Android iOS-. A/B , QUIC Uber. , , .

(95 99 ) – LTE, 3G, 2G.

9. QUIC TCP .


, – QUIC , , :


, , 80% QUIC , 15% QUIC TCP. , - , Cronet TCP , UDP- . , QUIC.

QUIC


, . . , , TCP QUIC . QUIC- .

, .

Source: https://habr.com/ru/post/de463073/


All Articles