QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen

QUIC-protokollen er ekstremt interessant at se, og derfor elsker vi at skrive om den. Men hvis tidligere udgivelser om QUIC mere var af historisk (lokalhistorie, hvis du vil) karakter og hardware, udgiver vi i dag gerne en oversættelse af en anden art - vi vil tale om den reelle anvendelse af protokollen i 2019. Desuden taler vi ikke om lille infrastruktur baseret i en såkaldt garage, men om Uber, der opererer næsten over hele verden. Hvordan virksomhedens ingeniører kom til beslutningen om at bruge QUIC i produktionen, hvordan de udførte testene, og hvad de så efter at have rullet det ud i produktionen - under skæringen.

Billederne er klikbare. God fornøjelse med at læse!

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen

Uber har en global skala, nemlig 600 byer med tilstedeværelse, i hver af hvilke applikationen udelukkende er afhængig af trådløst internet fra mere end 4500 mobiloperatører. Brugerne forventer, at appen ikke bare er hurtig, men i realtid – for at opnå dette har Uber-appen brug for lav latenstid og en meget pålidelig forbindelse. Ak, men stakken HTTP / 2 klarer sig ikke godt i dynamiske og tabsudsatte trådløse netværk. Vi indså, at i dette tilfælde er lav ydeevne direkte relateret til TCP-implementeringer i operativsystemkerner.

For at løse problemet søgte vi QUIC, en moderne kanalmultipleksingsprotokol, der giver os mere kontrol over transportprotokollens ydeevne. Aktuelt arbejdsgruppen IETF standardiserer QUIC as HTTP / 3.

Efter omfattende test konkluderede vi, at implementering af QUIC i vores applikation ville resultere i lavere hale latenser sammenlignet med TCP. Vi observerede reduktioner i intervallet 10-30 % for HTTPS-trafik i fører- og passagerapplikationer. QUIC gav os også ende-til-ende kontrol over brugerpakker.

I denne artikel deler vi vores erfaring med at optimere TCP til Uber-applikationer ved hjælp af en stak, der understøtter QUIC.

Den nyeste teknologi: TCP

I dag er TCP den mest brugte transportprotokol til levering af HTTPS-trafik på internettet. TCP giver en pålidelig strøm af bytes og håndterer derved netværksoverbelastning og tab af linklag. Den udbredte brug af TCP til HTTPS-trafik skyldes førstnævntes allestedsnærværende (næsten alle operativsystemer indeholder TCP), tilgængelighed på de fleste infrastrukturer (såsom belastningsbalancere, HTTPS-proxyer og CDN'er) og out-of-the-box funktionalitet, der er tilgængelig på næsten de fleste platforme og netværk.

De fleste brugere bruger vores app på farten, og TCP-haleforsinkelser var ikke i nærheden af ​​kravene fra vores HTTPS-trafik i realtid. Kort sagt, brugere over hele verden har oplevet dette - Figur 1 viser forsinkelser i større byer:

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 1: Tail latency varierer på tværs af Ubers hovedbyer.

Selvom latenstiden i indiske og brasilianske netværk var højere end i USA og Storbritannien, er halelatenstiden betydeligt højere end den gennemsnitlige latens. Og det gælder selv for USA og Storbritannien.

TCP over the air-ydelse

TCP blev oprettet til kablet netværk, det vil sige med vægt på meget forudsigelige links. Imidlertid, trådløs netværk har deres egne karakteristika og vanskeligheder. For det første er trådløse netværk modtagelige for tab på grund af interferens og signaldæmpning. For eksempel er Wi-Fi-netværk følsomme over for mikrobølger, bluetooth og andre radiobølger. Mobilnetværk lider af signaltab (tabt vej) på grund af refleksion/absorption af signalet af genstande og bygninger, samt fra interferens fra naboen celletårne. Dette fører til mere signifikant (4-10 gange) og mere forskelligartet Rundturstid (RTT) og pakketab sammenlignet med en kablet forbindelse.

For at bekæmpe båndbreddeudsving og tab bruger mobilnetværk typisk store buffere til trafikudbrud. Dette kan føre til for stor kø, hvilket betyder længere forsinkelser. Meget ofte behandler TCP denne kø som spild på grund af en forlænget timeout, så TCP har en tendens til at videresende og derved fylde bufferen. Dette problem er kendt som bufferbloat (overdreven netværksbuffring, bufferopsvulmning), og det er meget alvorligt problem moderne internet.

Endelig varierer mobilnetværkets ydeevne efter operatør, region og tid. I figur 2 indsamlede vi medianforsinkelserne for HTTPS-trafik på tværs af celler inden for et 2-kilometers interval. Data indsamlet for to store mobiloperatører i Delhi, Indien. Som du kan se, varierer ydeevnen fra celle til celle. Produktiviteten hos den ene operatør adskiller sig også fra den andens produktivitet. Dette er påvirket af faktorer som netværksadgangsmønstre, der tager højde for tid og placering, brugermobilitet, samt netværksinfrastruktur, der tager højde for tårntæthed og forholdet mellem netværkstyper (LTE, 3G, osv.).

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 2. Forsinkelser med en radius på 2 km som eksempel. Delhi, Indien.

Desuden varierer ydeevnen af ​​cellulære netværk over tid. Figur 3 viser median latens efter ugedag. Vi observerede også forskelle på en mindre skala inden for en enkelt dag og time.

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 3. Haleforsinkelser kan variere betydeligt mellem dage, men for den samme operatør.

Alt ovenstående forårsager, at TCP-ydeevnen er ineffektiv i trådløse netværk. Men før vi ledte efter alternativer til TCP, ønskede vi at udvikle en præcis forståelse af følgende punkter:

  • er TCP hovedsynderen bag hale latenser i vores applikationer?
  • Har moderne netværk betydelige og varierede rundrejseforsinkelser (RTT)?
  • Hvad er virkningen af ​​RTT og tab på TCP-ydelse?

TCP-ydelsesanalyse

For at forstå, hvordan vi analyserede TCP-ydeevne, lad os tage et hurtigt kig på, hvordan TCP overfører data fra en afsender til en modtager. Først etablerer afsenderen en TCP-forbindelse ved at udføre en tre-vejs håndtryk: Afsenderen sender en SYN-pakke, venter på en SYN-ACK-pakke fra modtageren og sender derefter en ACK-pakke. Et yderligere andet og tredje gennemløb er brugt på at etablere TCP-forbindelsen. Modtageren bekræfter modtagelsen af ​​hver pakke (ACK) for at sikre pålidelig levering.

Hvis en pakke eller ACK går tabt, sender afsenderen igen efter en timeout (RTO, timeout for gentransmission). RTO beregnes dynamisk baseret på forskellige faktorer, såsom den forventede RTT-forsinkelse mellem afsender og modtager.

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 4. Pakkeudveksling over TCP/TLS inkluderer en gentransmissionsmekanisme.

For at bestemme, hvordan TCP klarede sig i vores applikationer, overvågede vi TCP-pakker ved hjælp af tcpdump i en uge på kamptrafik, der kommer fra indiske kantservere. Vi analyserede derefter TCP-forbindelserne vha tcptrace. Derudover har vi oprettet en Android-applikation, der sender emuleret trafik til en testserver og efterligner rigtig trafik så meget som muligt. Smartphones med denne applikation blev distribueret til flere medarbejdere, som samlede logs over flere dage.

Resultaterne af begge forsøg stemte overens med hinanden. Vi så høje RTT-forsinkelser; haleværdier var næsten 6 gange højere end medianværdien; det aritmetiske gennemsnit af forsinkelser er mere end 1 sekund. Mange forbindelser var tabsgivende, hvilket fik TCP til at gentransmittere 3,5 % af alle pakker. I overbelastede områder som lufthavne og togstationer oplevede vi et tab på 7 %. Disse resultater sår tvivl om den konventionelle visdom, som dem, der bruges i cellulære netværk avancerede retransmissionskredsløb reducere tabene væsentligt på transportniveau. Nedenfor er testresultaterne fra "simulator"-applikationen:

Netværksmålinger
Værdier

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

RTT divergens, sekunder
I gennemsnit ~1,2 s

Pakketab på ustabile forbindelser
Gennemsnitlig ~3.5 % (7 % i overbelastede områder)

Næsten halvdelen af ​​disse forbindelser havde mindst ét ​​pakketab, de fleste af dem SYN- og SYN-ACK-pakker. De fleste TCP-implementeringer bruger en RTO-værdi på 1 sekund for SYN-pakker, som stiger eksponentielt for efterfølgende tab. Indlæsningstider for applikationer kan stige på grund af, at TCP tager længere tid at etablere forbindelser.

I tilfælde af datapakker reducerer høje RTO-værdier i høj grad den nyttige udnyttelse af netværket i nærvær af forbigående tab i trådløse netværk. Vi fandt ud af, at den gennemsnitlige retransmissionstid er cirka 1 sekund med en haleforsinkelse på næsten 30 sekunder. Disse høje latenstider på TCP-niveau forårsagede HTTPS-timeouts og genanmodninger, hvilket yderligere øgede netværkets latens og ineffektivitet.

Mens den 75. percentil af målt RTT var omkring 425 ms, var den 75. percentil for TCP næsten 3 sekunder. Dette antyder, at tabet fik TCP til at tage 7-10 gennemløb for at kunne overføre data. Dette kan være en konsekvens af ineffektiv RTO-beregning, TCP's manglende evne til hurtigt at reagere på tab seneste pakker i vinduet og ineffektiviteten af ​​overbelastningskontrolalgoritmen, som ikke skelner mellem trådløse tab og tab på grund af overbelastning af netværket. Nedenfor er resultaterne af TCP-tabstest:

TCP-pakketabsstatistikker
Value

Procentdel af forbindelser med mindst 1 pakketab
45 %

Procentdel af forbindelser med tab under forbindelsesopsætning
30 %

Procentdel af forbindelser med tab under dataudveksling
76 %

Fordeling af forsinkelser i retransmission, sekunder [50%, 75%, 95%,99%] [1, 2.8, 15, 28]

Fordeling af antallet af retransmissioner for én pakke eller TCP-segment
[1,3,6,7]

Anvendelse af QUIC

QUIC, der oprindeligt er udviklet af Google, er en multi-threaded moderne transportprotokol, der kører oven på UDP. I øjeblikket er QUIC inde standardiseringsprocessen (vi skrev allerede, at der så at sige er to versioner af QUIC, nysgerrigt kan følge linket – ca. oversætter). Som vist i figur 5 er QUIC placeret under HTTP/3 (faktisk er HTTP/2 oven på QUIC HTTP/3, som nu er ved at blive intensivt standardiseret). Det erstatter delvist HTTPS- og TCP-lagene ved at bruge UDP til at danne pakker. QUIC understøtter kun sikker dataoverførsel, da TLS er fuldt indbygget i QUIC.

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 5: QUIC kører under HTTP/3 og erstatter TLS, som tidligere kørte under HTTP/2.

Nedenfor er de grunde, der overbeviste os om at bruge QUIC til TCP-forstærkning:

  • 0-RTT forbindelse etablering. QUIC tillader genbrug af autorisationer fra tidligere forbindelser, hvilket reducerer antallet af sikkerhedshåndtryk. I fremtiden TLS1.3 vil understøtte 0-RTT, men et tre-vejs TCP-håndtryk vil stadig være påkrævet.
  • overvinde HoL-blokering. HTTP/2 bruger én TCP-forbindelse pr. klient for at forbedre ydeevnen, men dette kan føre til HoL-blokering (head-of-line). QUIC forenkler multipleksing og leverer anmodninger til applikationen uafhængigt.
  • trængselskontrol. QUIC ligger på applikationslaget, hvilket gør det nemmere at opdatere hovedtransportalgoritmen, der styrer afsendelse baseret på netværksparametre (antal tab eller RTT). De fleste TCP-implementeringer bruger algoritmen KUBIK, hvilket ikke er optimalt til latensfølsom trafik. Nyligt udviklede algoritmer som BBR, modellere netværket mere præcist og optimere latens. QUIC giver dig mulighed for at bruge BBR og opdatere denne algoritme, efterhånden som den bruges. forbedring.
  • genopfyldning af tab. QUIC kalder to TLP'er (haletabssonde) før RTO'en udløses - selv når tabene er meget mærkbare. Dette er forskelligt fra TCP-implementeringer. TLP gensender hovedsageligt den sidste pakke (eller den nye, hvis der er en) for at udløse hurtig genopfyldning. Håndtering af haleforsinkelser er især nyttig for den måde, Uber driver sit netværk på, nemlig til korte, sporadiske og latensfølsomme dataoverførsler.
  • optimeret ACK. Da hver pakke har et unikt sekvensnummer, er der ikke noget problem distinktioner pakker, når de gentransmitteres. ACK-pakker indeholder også tid til at behandle pakken og generere en ACK på klientsiden. Disse funktioner sikrer, at QUIC beregner RTT mere nøjagtigt. ACK i QUIC understøtter op til 256 bånd NACK, hvilket hjælper afsenderen med at være mere modstandsdygtig over for pakkeblanding og bruge færre bytes i processen. Selektiv ACK (SÆK) i TCP løser ikke dette problem i alle tilfælde.
  • forbindelsesmigrering. QUIC-forbindelser identificeres med et 64-bit ID, så hvis en klient ændrer IP-adresser, kan det gamle forbindelses-id fortsætte med at blive brugt på den nye IP-adresse uden afbrydelser. Dette er en meget almindelig praksis for mobilapplikationer, hvor brugeren skifter mellem Wi-Fi og mobilforbindelser.

Alternativer til QUIC

Vi overvejede alternative tilgange til at løse problemet, før vi valgte QUIC.

Det første, vi prøvede, var at implementere TPC PoPs (Points of Presence) for at afslutte TCP-forbindelser tættere på brugerne. I det væsentlige afslutter PoP'er en TCP-forbindelse med en mobilenhed tættere på det cellulære netværk og sender trafikken tilbage til den oprindelige infrastruktur. Ved at afslutte TCP tættere på, kan vi potentielt reducere RTT og sikre, at TCP er mere lydhør over for et dynamisk trådløst miljø. Vores eksperimenter har dog vist, at det meste af RTT og tab kommer fra cellulære netværk, og brugen af ​​PoP'er giver ikke væsentlig forbedring af ydeevnen.

Vi så også på tuning af TCP-parametre. Opsætning af en TCP-stak på vores heterogene edge-servere var vanskelig, fordi TCP har forskellige implementeringer på tværs af forskellige OS-versioner. Det var svært at implementere dette og teste forskellige netværkskonfigurationer. Konfiguration af TCP direkte på mobile enheder var ikke mulig på grund af manglende tilladelser. Endnu vigtigere er det, at funktioner såsom 0-RTT-forbindelser og forbedret RTT-forudsigelse er afgørende for protokollens arkitektur, og derfor er det umuligt at opnå væsentlige fordele ved at tune TCP alene.

Til sidst evaluerede vi adskillige UDP-baserede protokoller, der fejlfinder videostreaming - vi ville se, om disse protokoller ville hjælpe i vores tilfælde. Desværre manglede de alvorligt i mange sikkerhedsindstillinger og krævede også en ekstra TCP-forbindelse til metadata og kontroloplysninger.

Vores forskning har vist, at QUIC måske er den eneste protokol, der kan hjælpe med problemet med internettrafik, samtidig med at der tages hensyn til både sikkerhed og ydeevne.

Integration af QUIC i platformen

For at kunne integrere QUIC og forbedre applikationsydelsen i miljøer med dårlige tilslutningsmuligheder, erstattede vi den gamle stak (HTTP/2 over TLS/TCP) med QUIC-protokollen. Vi brugte netværksbiblioteket Cronet af Chromium-projekter, som indeholder den originale Google-version af protokollen - gQUIC. Denne implementering bliver også konstant forbedret for at følge den seneste IETF-specifikation.

Vi integrerede først Cronet i vores Android-apps for at tilføje support til QUIC. Integration blev gennemført på en sådan måde, at migrationsomkostningerne blev reduceret mest muligt. I stedet for fuldstændig at erstatte den gamle netværksstak, der brugte biblioteket OkHttp, har vi integreret Cronet UNDER OkHttp API-rammeværket. Ved at gøre integrationen på denne måde undgik vi ændringer i vores netværksopkald (som bruges af Retrofit) på API-niveau.

I lighed med tilgangen til Android-enheder implementerede vi Cronet i Uber-apps på iOS og opfangede HTTP-trafik fra netværket APIved brug af NSURL-protokollen. Denne abstraktion, leveret af iOS Foundation, håndterer protokolspecifikke URL-data og sikrer, at vi kan integrere Cronet i vores iOS-applikationer uden væsentlige migreringsomkostninger.

Gennemførelse af QUIC på Google Cloud Balancers

På backend-siden leveres QUIC-afslutningen af ​​Google Cloud Load Balancing-infrastrukturen, som bruger alt-svc overskrifter som svar på support QUIC. Generelt tilføjer balanceren en alt-svc-header til hver HTTP-anmodning, og dette validerer allerede QUIC-understøttelse for domænet. Når en Cronet-klient modtager et HTTP-svar med denne header, bruger den QUIC til efterfølgende HTTP-anmodninger til det pågældende domæne. Når balanceren har gennemført QUIC, sender vores infrastruktur eksplicit denne handling over HTTP2/TCP til vores datacentre.

Ydelse: Resultater

Outputydeevne er hovedårsagen til vores søgen efter en bedre protokol. Til at begynde med lavede vi en stand med netværksemuleringfor at finde ud af, hvordan QUIC vil opføre sig under forskellige netværksprofiler. For at teste QUICs ydeevne på netværk i den virkelige verden kørte vi eksperimenter, mens vi kørte rundt i New Delhi ved at bruge emuleret netværkstrafik meget lig HTTP-opkald i passagerappen.

Forsøg 1

Udstyr til forsøget:

  • test Android-enheder med OkHttp- og Cronet-stakke for at sikre, at vi tillader HTTPS-trafik over henholdsvis TCP og QUIC;
  • en Java-baseret emuleringsserver, der sender den samme type HTTPS-headere i svar og indlæser klientenheder for at modtage anmodninger fra dem;
  • cloud-proxyer, der fysisk er placeret tæt på Indien for at afslutte TCP- og QUIC-forbindelser. Mens vi til TCP-opsigelse brugte en omvendt proxy på Nginx, var det svært at finde en open source omvendt proxy til QUIC. Vi byggede selv en omvendt proxy til QUIC ved at bruge den grundlæggende QUIC-stak fra Chromium og offentliggjort det til chrom som open source.

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnenQUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 6. TCP vs QUIC road test-pakken bestod af Android-enheder med OkHttp og Cronet, cloud-proxyer til afslutning af forbindelser og en emuleringsserver.

Forsøg 2

Da Google gjorde QUIC tilgængelig med Google Cloud Load Balancing, vi brugte den samme beholdning, men med en modifikation: I stedet for NGINX tog vi Google load balancers til at afslutte TCP- og QUIC-forbindelser fra enheder, samt for at dirigere HTTPS-trafik til emuleringsserveren. Balancere er distribueret over hele verden, men bruger den PoP-server, der er tættest på enheden (takket være geolocation).

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 7. I det andet eksperiment ønskede vi at sammenligne færdiggørelsestiden for TCP og QUIC: ved at bruge Google Cloud og bruge vores cloud-proxy.

Som et resultat ventede flere afsløringer os:

  • opsigelse via PoP forbedret TCP-ydelse. Da balancere afslutter TCP-forbindelser tættere på brugerne og er meget optimerede, resulterer dette i lavere RTT'er, hvilket forbedrer TCP-ydeevnen. Og selvom QUIC var mindre påvirket, klarede det sig stadig bedre end TCP med hensyn til at reducere halelatenstiden (med 10-30 procent).
  • haler er påvirket netværk humle. Selvom vores QUIC-proxy var længere væk fra enhederne (ca. 50 ms højere latency) end Googles load balancers, leverede den lignende ydeevne - en 15 % reduktion i latens versus en 20 % reduktion i 99. percentilen for TCP. Dette tyder på, at den sidste mile overgang er en flaskehals i netværket.

QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnenQUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 8: Resultater fra to eksperimenter viser, at QUIC overgår TCP væsentligt.

Bekæmp trafikken

Inspireret af eksperimenter har vi implementeret QUIC-support i vores Android- og iOS-applikationer. Vi udførte A/B-tests for at bestemme virkningen af ​​QUIC i de byer, hvor Uber opererer. Generelt så vi en betydelig reduktion i haleforsinkelser på tværs af både regioner, teleoperatører og netværkstype.

Graferne nedenfor viser de procentvise forbedringer i haler (95 og 99 percentiler) efter makroregion og forskellige netværkstyper - LTE, 3G, 2G.
QUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnenQUIC-protokollen i aktion: hvordan Uber implementerede den for at optimere ydeevnen
Figur 9. I kamptests overgik QUIC TCP med hensyn til latency.

Kun fremad

Måske er dette kun begyndelsen - frigivelsen af ​​QUIC til produktion har givet fantastiske muligheder for at forbedre applikationsydelsen i både stabile og ustabile netværk, nemlig:

Øget dækning

Efter at have analyseret protokollens ydeevne på reel trafik, så vi, at ca. 80 % af sessionerne med succes brugte QUIC til Alle anmodninger, mens 15 % af sessionerne brugte en kombination af QUIC og TCP. Vi antager, at kombinationen skyldes, at Cronet-biblioteket timeout tilbage til TCP, da det ikke kan skelne mellem reelle UDP-fejl og dårlige netværksforhold. Vi undersøger i øjeblikket en løsning på dette problem, mens vi arbejder hen imod den efterfølgende implementering af QUIC.

QUIC optimering

Trafik fra mobilapps er latensfølsom, men ikke båndbreddefølsom. Vores applikationer bruges også primært på mobilnetværk. Baseret på eksperimenter er halelatenserne stadig høje, selvom man bruger en proxy til at afslutte TCP og QUIC tæt på brugerne. Vi leder aktivt efter måder at forbedre håndteringen af ​​overbelastning og forbedre effektiviteten af ​​QUIC-tabsgendannelsesalgoritmer.

Med disse og flere andre forbedringer planlægger vi at forbedre brugeroplevelsen uanset netværk og region, hvilket gør bekvem og problemfri pakketransport mere tilgængelig over hele verden.

Kilde: www.habr.com

Tilføj en kommentar