Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu

Protokol QUIC je nesmírně zajímavé sledovat, a proto o něm rádi píšeme. Pokud ale předchozí publikace o QUIC byly spíše historického (lokální historie, chcete-li) povahy a hardwaru, dnes rádi zveřejníme překlad jiného druhu – o skutečné aplikaci protokolu si povíme v roce 2019. Navíc se nebavíme o malé infrastruktuře založené takzvaně v garáži, ale o Uberu, který působí téměř po celém světě. Jak inženýři společnosti dospěli k rozhodnutí použít QUIC ve výrobě, jak provedli testy a co viděli po zavedení do výroby - pod řezem.

Obrázky jsou klikatelné. Příjemné čtení!

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu

Uber má globální měřítko, konkrétně 600 měst přítomnosti, v každém z nich se aplikace zcela spoléhá na bezdrátový internet od více než 4500 XNUMX mobilních operátorů. Uživatelé očekávají, že aplikace bude nejen rychlá, ale v reálném čase – k dosažení tohoto cíle potřebuje aplikace Uber nízkou latenci a velmi spolehlivé připojení. Bohužel, ale hromada HTTP / 2 nefunguje dobře v dynamických bezdrátových sítích náchylných ke ztrátám. Uvědomili jsme si, že v tomto případě slabý výkon přímo souvisí s implementacemi TCP v jádrech operačního systému.

Abychom problém vyřešili, přihlásili jsme se QUIC, moderní protokol multiplexování kanálů, který nám poskytuje větší kontrolu nad výkonem přenosového protokolu. V současné době pracovní skupina IETF standardizuje QUIC as HTTP / 3.

Po rozsáhlém testování jsme dospěli k závěru, že implementace QUIC do naší aplikace by ve srovnání s TCP měla za následek nižší latence. Pozorovali jsme snížení v rozsahu 10–30 % pro provoz HTTPS v aplikacích pro řidiče a spolujezdce. QUIC nám také poskytl úplnou kontrolu nad uživatelskými balíčky.

V tomto článku sdílíme naše zkušenosti s optimalizací TCP pro aplikace Uber pomocí zásobníku, který podporuje QUIC.

Nejnovější technologie: TCP

Dnes je TCP nejpoužívanějším transportním protokolem pro doručování HTTPS provozu na internetu. TCP poskytuje spolehlivý proud bajtů, čímž se vyrovnává s přetížením sítě a ztrátami na linkové vrstvě. Široké použití TCP pro provoz HTTPS je způsobeno všudypřítomností prvního (téměř každý OS obsahuje TCP), dostupností na většině infrastruktury (jako jsou nástroje pro vyrovnávání zátěže, HTTPS proxy a CDN) a předdefinovanou funkčností, která je k dispozici. na téměř většině platforem a sítí.

Většina uživatelů používá naši aplikaci na cestách a latence TCP se ani zdaleka neblížily požadavkům našeho provozu HTTPS v reálném čase. Jednoduše řečeno, uživatelé na celém světě to zažili – Obrázek 1 ukazuje zpoždění ve velkých městech:

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 1: Latence ocasu se v hlavních městech Uberu liší.

Ačkoli byla latence v indických a brazilských sítích vyšší než v USA a Velké Británii, latence na konci je výrazně vyšší než průměrná latence. A to platí i pro USA a Velkou Británii.

Výkon TCP vzduchem

TCP byl vytvořen pro drátové sítí, tedy s důrazem na vysoce předvídatelné vazby. Nicméně, bezdrátový sítě mají své vlastní charakteristiky a potíže. Za prvé, bezdrátové sítě jsou náchylné ke ztrátám v důsledku rušení a útlumu signálu. Například sítě Wi-Fi jsou citlivé na mikrovlny, bluetooth a další rádiové vlny. Mobilní sítě trpí ztrátou signálu (ztracená cesta) v důsledku odrazu/absorpce signálu předměty a budovami, jakož i od rušení ze sousedního buněčné věže. To vede k významnějším (4-10krát) a rozmanitějším Doba zpáteční cesty (RTT) a ztráta paketů ve srovnání s kabelovým připojením.

K boji proti kolísání a ztrátám šířky pásma mobilní sítě obvykle používají velké vyrovnávací paměti pro dopravní výpadky. To může vést k nadměrnému řazení ve frontě, což znamená delší zpoždění. TCP velmi často zachází s tímto řazením do fronty jako s plýtváním kvůli prodlouženému časovému limitu, takže TCP má tendenci se přenášet a tím zaplňovat vyrovnávací paměť. Tento problém je známý jako bufferbloat (nadměrné ukládání do vyrovnávací paměti sítě, nafouknutí vyrovnávací paměti), a to je velmi vážný problém moderní internet.

A konečně, výkon mobilní sítě se liší podle operátora, regionu a času. Na obrázku 2 jsme shromáždili střední zpoždění provozu HTTPS napříč buňkami v rozsahu 2 kilometrů. Data shromážděná pro dva hlavní mobilní operátory v Dillí v Indii. Jak vidíte, výkon se liší buňku od buňky. Také produktivita jednoho operátora se liší od produktivity druhého. To je ovlivněno faktory, jako jsou vzorce vstupu do sítě zohledňující čas a místo, mobilita uživatelů a také síťová infrastruktura zohledňující hustotu věží a poměr typů sítí (LTE, 3G atd.).

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 2. Zpoždění s použitím poloměru 2 km jako příkladu. Dillí, Indie.

Také výkon celulárních sítí se v průběhu času mění. Obrázek 3 ukazuje střední latenci podle dne v týdnu. Pozorovali jsme také rozdíly v menším měřítku, během jediného dne a hodiny.

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 3. Zpoždění ocasu se může mezi dny výrazně lišit, ale pro stejného operátora.

Vše výše uvedené způsobuje, že výkon TCP je v bezdrátových sítích neúčinný. Před hledáním alternativ k TCP jsme však chtěli přesně porozumět následujícím bodům:

  • je TCP hlavním viníkem pozdních latencí v našich aplikacích?
  • Mají moderní sítě významná a různá zpáteční zpoždění (RTT)?
  • Jaký je dopad RTT a ztráty na výkon TCP?

Analýza výkonu TCP

Abychom pochopili, jak jsme analyzovali výkon TCP, pojďme se rychle podívat na to, jak TCP přenáší data od odesílatele k přijímači. Nejprve odesílatel naváže spojení TCP, přičemž provede třícestné spojení podání ruky: Odesílatel odešle paket SYN, čeká na paket SYN-ACK od příjemce a poté odešle paket ACK. Další druhý a třetí průchod se stráví navázáním spojení TCP. Příjemce potvrzuje přijetí každého paketu (ACK), aby bylo zajištěno spolehlivé doručení.

Pokud dojde ke ztrátě paketu nebo ACK, odesílatel po uplynutí časového limitu znovu odešle (RTO, časový limit opětovného přenosu). RTO se vypočítává dynamicky na základě různých faktorů, jako je očekávané zpoždění RTT mezi odesílatelem a příjemcem.

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 4. Výměna paketů přes TCP/TLS zahrnuje mechanismus opakovaného přenosu.

Abychom zjistili, jak TCP fungoval v našich aplikacích, sledovali jsme pomocí TCP paketů tcpdump na týden o bojovém provozu přicházejícím z indických okrajových serverů. Poté jsme analyzovali TCP spojení pomocí tcptrace. Kromě toho jsme vytvořili aplikaci pro Android, která odesílá emulovaný provoz na testovací server a co nejvíce napodobuje skutečný provoz. Smartphony s touto aplikací byly distribuovány několika zaměstnancům, kteří během několika dní sbírali protokoly.

Výsledky obou experimentů byly vzájemně konzistentní. Viděli jsme vysoké latence RTT; hodnoty ocasu byly téměř 6krát vyšší než střední hodnota; aritmetický průměr zpoždění je více než 1 sekunda. Mnoho spojení bylo ztrátových, což způsobilo, že TCP znovu přenesl 3,5 % všech paketů. V přetížených oblastech, jako jsou letiště a vlaková nádraží, jsme zaznamenali 7% ztráty. Tyto výsledky zpochybňují konvenční moudrost, která se používá v celulárních sítích pokročilé retranslační obvody výrazně snížit ztráty na úrovni dopravy. Níže jsou uvedeny výsledky testů z aplikace „simulátor“:

Síťové metriky
Hodnoty

RTT, milisekundy [50%,75%, 95%,99%]
[350, 425, 725, 2300]

RTT divergence, sekundy
V průměru ~1,2 s

Ztráta paketů na nestabilních spojeních
Průměr ~3.5 % (7 % v přetížených oblastech)

Téměř polovina těchto spojení měla alespoň jednu ztrátu paketu, většina z nich pakety SYN a SYN-ACK. Většina implementací TCP používá pro pakety SYN hodnotu RTO 1 sekundu, která se exponenciálně zvyšuje pro následné ztráty. Časy načítání aplikací se mohou prodloužit, protože TCP trvá déle, než naváže spojení.

V případě datových paketů vysoké hodnoty RTO výrazně snižují užitečné využití sítě za přítomnosti přechodných ztrát v bezdrátových sítích. Zjistili jsme, že průměrná doba opětovného přenosu je přibližně 1 sekunda se zpožděním téměř 30 sekund. Tyto vysoké latence na úrovni TCP způsobovaly časové limity HTTPS a opakované požadavky, což dále zvyšovalo latenci sítě a neefektivitu.

Zatímco 75. percentil naměřeného RTT byl kolem 425 ms, 75. percentil pro TCP byl téměř 3 sekundy. To naznačuje, že ztráta způsobila, že TCP potřeboval 7-10 průchodů, aby úspěšně přenesl data. To může být důsledek neefektivního výpočtu RTO, neschopnosti TCP rychle reagovat na ztrátu nejnovější balíčky v okně a neefektivnost algoritmu řízení přetížení, který nerozlišuje mezi bezdrátovými ztrátami a ztrátami v důsledku přetížení sítě. Níže jsou uvedeny výsledky testů ztráty TCP:

Statistika ztráty paketů TCP
Hodnota

Procento připojení s alespoň 1 ztrátou paketu
45%

Procento připojení se ztrátami během nastavování připojení
30%

Procento spojení se ztrátami během výměny dat
76%

Rozdělení zpoždění při opakovaném přenosu, sekundy [50 %, 75 %, 95 %, 99 %] [1, 2.8, 15, 28]

Rozdělení počtu opakovaných přenosů pro jeden paket nebo TCP segment
[1,3,6,7]

Aplikace QUIC

QUIC, původně vyvinutý společností Google, je vícevláknový moderní transportní protokol, který běží nad UDP. V současné době je zde QUIC standardizační proces (Už jsme psali, že existují dvě verze QUIC, zajímavé můžete sledovat odkaz - Cca. překladatel). Jak je znázorněno na obrázku 5, QUIC je umístěn pod HTTP/3 (ve skutečnosti je HTTP/2 nad QUIC HTTP/3, který je nyní intenzivně standardizován). Částečně nahrazuje vrstvy HTTPS a TCP pomocí UDP k vytváření paketů. QUIC podporuje pouze zabezpečený přenos dat, protože TLS je plně integrován do QUIC.

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 5: QUIC běží pod HTTP/3 a nahrazuje TLS, které dříve běželo pod HTTP/2.

Níže jsou uvedeny důvody, které nás přesvědčily k použití QUIC pro zesílení TCP:

  • Navázání připojení 0-RTT. QUIC umožňuje opětovné použití oprávnění z předchozích připojení, čímž se snižuje počet bezpečnostních handshaků. Napříště TLS1.3 bude podporovat 0-RTT, ale stále bude vyžadován třícestný TCP handshake.
  • překonání blokování HoL. HTTP/2 používá jedno TCP spojení na klienta ke zlepšení výkonu, ale to může vést k blokování HoL (head-of-line). QUIC zjednodušuje multiplexování a doručuje požadavky do aplikace nezávisle.
  • kontrola přetížení. QUIC sídlí na aplikační vrstvě, což usnadňuje aktualizaci hlavního transportního algoritmu, který řídí odesílání na základě síťových parametrů (počet ztrát nebo RTT). Většina implementací TCP používá tento algoritmus KRYCHLOVÝ, což není optimální pro provoz citlivý na latenci. Nedávno vyvinuté algoritmy jako BBR, přesněji modelovat síť a optimalizovat latenci. QUIC vám umožňuje používat BBR a aktualizovat tento algoritmus tak, jak se používá. zlepšování.
  • doplnění ztrát. QUIC volá dva TLP (sonda ztráty ocasu) před spuštěním RTO - i když jsou ztráty velmi znatelné. To se liší od implementací TCP. TLP znovu vysílá hlavně poslední paket (nebo nový, pokud nějaký existuje), aby spustil rychlé doplňování. Zvládání zpoždění na konci je zvláště užitečné pro způsob, jakým Uber provozuje svou síť, konkrétně pro krátké, sporadické a na latenci citlivé datové přenosy.
  • optimalizované ACK. Protože každý paket má jedinečné pořadové číslo, není problém rozdíly pakety, když jsou znovu vysílány. Pakety ACK také obsahují čas na zpracování paketu a vygenerování ACK na straně klienta. Tyto funkce zajišťují, že QUIC počítá RTT přesněji. ACK v QUIC podporuje až 256 pásem NACK, což pomáhá odesílateli být odolnější vůči míchání paketů a používat méně bajtů v procesu. Selektivní ACK (SACK) v TCP neřeší tento problém ve všech případech.
  • migrace připojení. Připojení QUIC jsou identifikována 64bitovým ID, takže pokud klient změní adresy IP, může být na nové adrese IP bez přerušení nadále používáno staré ID připojení. Toto je velmi běžná praxe u mobilních aplikací, kde uživatel přepíná mezi Wi-Fi a mobilním připojením.

Alternativy k QUIC

Před výběrem QUIC jsme zvažovali alternativní přístupy k řešení problému.

První věc, kterou jsme zkusili, bylo nasazení TPC PoPs (Points of Presence) pro ukončení TCP spojení blíže k uživatelům. PoPs v podstatě ukončí TCP spojení s mobilním zařízením blíže k mobilní síti a proxy provoz zpět do původní infrastruktury. Bližším ukončením TCP můžeme potenciálně snížit RTT a zajistit, že TCP bude lépe reagovat na dynamické bezdrátové prostředí. Naše experimenty však ukázaly, že většina RTT a ztrát pochází z celulárních sítí a použití PoP neposkytuje významné zlepšení výkonu.

Podívali jsme se také na ladění parametrů TCP. Nastavení zásobníku TCP na našich heterogenních okrajových serverech bylo obtížné, protože TCP má různé implementace v různých verzích OS. Bylo obtížné to implementovat a testovat různé konfigurace sítě. Konfigurace TCP přímo na mobilních zařízeních nebyla možná kvůli nedostatku oprávnění. Ještě důležitější je, že funkce jako připojení 0-RTT a vylepšená predikce RTT jsou pro architekturu protokolu kritické, a proto není možné dosáhnout významných výhod pouze vyladěním TCP.

Nakonec jsme vyhodnotili několik protokolů založených na UDP, které řeší problémy se streamováním videa – chtěli jsme zjistit, zda by tyto protokoly pomohly v našem případě. Bohužel jim velmi chybělo mnoho nastavení zabezpečení a také vyžadovaly dodatečné připojení TCP pro metadata a řídicí informace.

Náš výzkum ukázal, že QUIC je snad jediným protokolem, který může pomoci s problémem internetového provozu, přičemž bere v úvahu jak bezpečnost, tak výkon.

Integrace QUIC do platformy

Abychom úspěšně začlenili QUIC a zlepšili výkon aplikací v prostředích se špatnou konektivitou, nahradili jsme starý zásobník (HTTP/2 přes TLS/TCP) protokolem QUIC. Použili jsme síťovou knihovnu Cronet z Projekty Chromium, který obsahuje původní, Google verzi protokolu - gQUIC. Tato implementace je také neustále vylepšována, aby odpovídala nejnovější specifikaci IETF.

Nejprve jsme do našich aplikací pro Android integrovali Cronet, abychom přidali podporu pro QUIC. Integrace byla provedena tak, aby se co nejvíce snížily náklady na migraci. Místo úplného nahrazení starého síťového zásobníku, který používal knihovnu OkHttp, integrovali jsme Cronet POD rámcem API OkHttp. Tím, že jsme provedli integraci tímto způsobem, jsme se vyhnuli změnám našich síťových hovorů (které používají Retrofit) na úrovni API.

Podobně jako u zařízení se systémem Android jsme implementovali Cronet do aplikací Uber na iOS a zachytili jsme HTTP provoz ze sítě APIPoužití NSURLProtocol. Tato abstrakce, kterou poskytuje iOS Foundation, zpracovává data URL specifická pro protokol a zajišťuje, že můžeme integrovat Cronet do našich aplikací pro iOS bez značných nákladů na migraci.

Dokončení QUIC na Google Cloud Balancers

Na straně backendu je dokončení QUIC zajišťováno infrastrukturou pro vyrovnávání zátěže Google Cloud, kterou využívá alt-svc hlavičky v odpovědích na podporu QUIC. Balancér obecně přidává ke každému požadavku HTTP hlavičku alt-svc, což již ověřuje podporu QUIC pro doménu. Když klient Cronet obdrží odpověď HTTP s touto hlavičkou, použije QUIC pro následné požadavky HTTP do této domény. Jakmile balancer dokončí QUIC, naše infrastruktura tuto akci explicitně odešle přes HTTP2/TCP do našich datových center.

Výkon: Výsledky

Výstupní výkon je hlavním důvodem našeho hledání lepšího protokolu. Pro začátek jsme vytvořili stojan s síťová emulacezjistit, jak se bude QUIC chovat v různých síťových profilech. Abychom otestovali výkon QUIC v reálných sítích, provedli jsme experimenty při jízdě po Novém Dillí s použitím emulovaného síťového provozu velmi podobného volání HTTP v aplikaci pro cestující.

Experiment 1

Vybavení pro experiment:

  • otestujte zařízení Android pomocí zásobníků OkHttp a Cronet, abyste zajistili, že povolíme provoz HTTPS přes TCP a QUIC;
  • emulační server na bázi Java, který odesílá stejný typ HTTPS hlaviček v odpovědích a načítá klientská zařízení, aby od nich přijímala požadavky;
  • cloudové proxy, které se fyzicky nacházejí v blízkosti Indie, aby ukončily připojení TCP a QUIC. Zatímco pro ukončení TCP jsme použili reverzní proxy Nginx, bylo obtížné najít open source reverzní proxy pro QUIC. Sami jsme vytvořili reverzní proxy pro QUIC pomocí základního zásobníku QUIC od Chromium a publikováno to do chromu jako open source.

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonuProtokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 6. Sada silničních testů TCP vs QUIC sestávala ze zařízení Android s OkHttp a Cronet, cloudových proxy pro ukončování připojení a emulačního serveru.

Experiment 2

Když Google zpřístupnil QUIC s Google Cloud Load Balancing, použili jsme stejný inventář, ale s jednou úpravou: místo NGINX jsme použili nástroje pro vyrovnávání zatížení Google, abychom ukončili připojení TCP a QUIC ze zařízení a také směrovali provoz HTTPS na emulační server. Balancery jsou distribuovány po celém světě, ale používají PoP server nejblíže k zařízení (díky geolokaci).

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 7. Ve druhém experimentu jsme chtěli porovnat latenci dokončení TCP a QUIC: pomocí Google Cloud a pomocí našeho cloudového proxy.

V důsledku toho nás čekalo několik odhalení:

  • ukončení přes PoP zlepšilo výkon TCP. Vzhledem k tomu, že balancery ukončují TCP spojení blíže k uživatelům a jsou vysoce optimalizované, výsledkem jsou nižší RTT, což zlepšuje výkon TCP. A i když byl QUIC ovlivněn méně, stále předčil TCP z hlediska snížení latence ocasu (o 10–30 procent).
  • ocasy jsou ovlivněny síťové skoky. Přestože byl náš proxy QUIC dále od zařízení (asi o 50 ms vyšší latence) než nástroje pro vyrovnávání zátěže Google, poskytoval podobný výkon – 15% snížení latence oproti 20% snížení 99. percentilu pro TCP. To naznačuje, že přechod na poslední míli je úzkým hrdlem v síti.

Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonuProtokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 8: Výsledky dvou experimentů ukazují, že QUIC výrazně překonává TCP.

Bojový provoz

Inspirováni experimentováním jsme implementovali podporu QUIC do našich aplikací pro Android a iOS. Provedli jsme A/B testování, abychom zjistili dopad QUIC ve městech, kde Uber působí. Obecně jsme zaznamenali výrazné snížení zpoždění na konci v obou regionech, telekomunikačních operátorech a typu sítě.

Níže uvedené grafy ukazují procentuální zlepšení koncových bodů (95 a 99 percentilů) podle makroregionů a různých typů sítí – LTE, 3G, 2G.
Protokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonuProtokol QUIC v akci: jak jej Uber implementoval k optimalizaci výkonu
Obrázek 9. V bitevních testech QUIC překonal TCP z hlediska latence.

Pouze vpřed

Možná je to jen začátek – uvedení QUIC do produkce poskytlo úžasné příležitosti ke zlepšení výkonu aplikací ve stabilních i nestabilních sítích, konkrétně:

Zvýšené pokrytí

Po analýze výkonu protokolu na skutečném provozu jsme viděli, že přibližně 80 % relací úspěšně použilo QUIC pro vše požadavky, zatímco 15 % relací používalo kombinaci QUIC a TCP. Předpokládáme, že tato kombinace je způsobena časovým limitem knihovny Cronet zpět na TCP, protože nedokáže rozlišit mezi skutečnými selháními UDP a špatnými podmínkami sítě. V současné době hledáme řešení tohoto problému a pracujeme na následné implementaci QUIC.

QUIC optimalizace

Provoz z mobilních aplikací je citlivý na latenci, ale ne na šířku pásma. Naše aplikace se také primárně používají v mobilních sítích. Na základě experimentů jsou latence ocasu stále vysoké, i když používáte proxy k ukončení TCP a QUIC v blízkosti uživatelů. Aktivně hledáme způsoby, jak zlepšit řízení přetížení a zlepšit efektivitu algoritmů obnovy ztrát QUIC.

S těmito a několika dalšími vylepšeními plánujeme zlepšit uživatelskou zkušenost bez ohledu na síť a region, aby byl pohodlný a bezproblémový přenos paketů dostupnější po celém světě.

Zdroj: www.habr.com

Přidat komentář