Hoe om te gaan met tail-latentie
- 13 minuten
We hebben al verschillende optimalisatietechnieken besproken die in de cloud worden gebruikt om de latentie te verminderen. Enkele van de metingen die we hebben bestudeerd, zijn het horizontaal of verticaal schalen van resources en het gebruik van een load balancer om aanvragen te routeren naar de dichtstbijzijnde beschikbare resources. Op deze pagina wordt dieper ingegaan op waarom, in een groot datacenter of cloudtoepassing, het belangrijk is om de latentie voor alle aanvragen te minimaliseren en niet alleen te optimaliseren voor het algemene geval. We gaan onderzoeken hoe zelfs een paar uitschieters met hoge latentie de waargenomen prestaties van een groot systeem aanzienlijk kunnen verslechteren. Deze pagina bevat ook verschillende technieken voor het maken van services die voorspelbare reacties met lage latentie bieden, zelfs als de afzonderlijke onderdelen dit niet garanderen. Dit is een probleem dat vooral belangrijk is voor interactieve toepassingen waarbij de gewenste latentie voor een interactie lager is dan 100 ms.
Wat is tail-latentie?
De meeste cloudtoepassingen zijn grote, gedistribueerde systemen die vaak afhankelijk zijn van parallelle uitvoering om de latentie te verminderen. Een veelvoorkomende techniek is het uitwaaieren van een aanvraag die is ontvangen op een hoofdknooppunt (bijvoorbeeld een front-endwebserver) op veel leaf-knooppunten (back-end-rekenservers). De prestatieverbetering wordt aangestuurd door de parallelle uitvoering van de gedistribueerde berekening en ook door het feit dat extreem dure kosten voor het verplaatsen van gegevens worden vermeden. We verplaatsen de berekening naar de plaats waar de gegevens worden opgeslagen. Natuurlijk werkt elk leaf-knooppunt gelijktijdig op honderden of zelfs duizenden parallelle aanvragen.
Afbeelding 7: Latentie door uitschalen
Bekijk het voorbeeld van het zoeken naar een film op Netflix. Als een gebruiker begint te typen in het zoekvak, genereert dit verschillende parallelle gebeurtenissen van de hoofdwebserver. Deze gebeurtenissen omvatten minimaal de volgende aanvragen:
- Voor de automatische aanvulengine, om daadwerkelijk de zoekopdracht te voorspellen op basis van eerdere trends en het gebruikersprofiel.
- Voor de correctie-engine, waarmee fouten in de getypte query worden gevonden op basis van een voortdurend aanpassend taalmodel.
- Afzonderlijke zoekresultaten voor elk van de onderdeelwoorden van een query met meerdere woorden, die moeten worden gecombineerd op basis van de positie en relevantie van de films.
- Aanvullende naverwerking en filtering van resultaten om te voldoen aan de voorkeuren voor veilig zoeken van de gebruiker.
Dergelijke voorbeelden zijn zeer gebruikelijk. Een enkele Facebook-aanvraag is bekend om contact op te maken met duizenden memcached servers, terwijl één Bing-zoekopdracht vaak contact maakt met meer dan tienduizend indexservers.
Het is duidelijk dat de behoefte aan schaal heeft geleid tot een grote fan-out aan de back-end voor elk afzonderlijk verzoek dat door de front-end wordt bediend. Voor services die naar verwachting 'responsief' zijn om hun gebruikersbestand te behouden, tonen heuristieken aan dat reacties binnen 100 ms worden verwacht. Naarmate het aantal servers dat nodig is om een query op te lossen toeneemt, is de totale tijd vaak afhankelijk van het slechtst presterende antwoord van een leaf-knooppunt naar een hoofdknooppunt. Ervan uitgaande dat alle leaf-knooppunten moeten worden uitgevoerd voordat een resultaat kan worden geretourneerd, moet de algehele latentie altijd groter zijn dan de latentie van het ene langzaamste onderdeel.
Net als bij de meeste stochastische processen kan de reactietijd van één leaf-knooppunt worden uitgedrukt als een verdeling. Tientallen jaren ervaring hebben aangetoond dat in het algemeen de meeste (>99%) aanvragen van een goed geconfigureerd cloudsysteem zeer snel worden uitgevoerd. Maar vaak zijn er zeer weinig uitbijters op een systeem dat extreem langzaam wordt uitgevoerd.
afbeelding 8: Voorbeeld van taillatentie5
Overweeg een systeem waarbij alle leaf-knooppunten een gemiddelde reactietijd van 1 ms hebben, maar er een kans is van 1% dat de reactietijd groter is dan 1000 ms (één seconde). Als elke query wordt verwerkt door slechts één leaf-knooppunt, is de kans dat de query langer duurt dan één seconde ook 1%. Als we echter het aantal knooppunten verhogen naar 100, neemt de kans dat de query binnen één seconde eindigt af op 36,6%, wat betekent dat er een kans van 63,4% kans is dat de queryduur wordt bepaald door de staart (laagste 1%) van de latentieverdeling.
$(.99^{100})$
Als we dit simuleren voor verschillende gevallen, zien we dat naarmate het aantal servers toeneemt, de impact van één langzame query duidelijker is (u ziet dat de onderstaande grafiek monotonisch toeneemt). Naarmate de waarschijnlijkheid van deze uitbijters afneemt van 1% tot 0,01%, presteert het systeem aanzienlijk slechter.
afbeelding 9: Recente studie van de kans op reactietijd die de 50e, 95e en 99e percentielen toont voor latentie van aanvragen4
Net zoals we onze toepassingen hebben ontworpen om fouttolerant te zijn voor het oplossen van problemen met de betrouwbaarheid van resources, moet het nu duidelijk zijn waarom het belangrijk is voor toepassingen om 'tail tolerant' te zijn. Om dit te kunnen doen, moeten we de bronnen van deze lange prestatievariabiliteit begrijpen en waar mogelijk oplossingen en tijdelijke oplossingen identificeren.
Variabiliteit in de cloud: bronnen en oplossingen
Om de variabiliteit van de reactietijd op te lossen die leidt tot dit probleem met staartlatentie, moeten we de bronnen van de prestatievariabiliteit begrijpen.1
- Gebruik van gedeelde resources: veel verschillende VM's (en toepassingen binnen die VM's) hebben betrekking op een gedeelde pool met rekenresources. In zeldzame gevallen is het mogelijk dat deze conflicten leiden tot een lage latentie voor sommige aanvragen. Voor kritieke taken kan het zinvol zijn om toegewezen exemplaren te gebruiken en regelmatig benchmarks uit te voeren wanneer ze inactief zijn, om ervoor te zorgen dat deze zich correct gedraagt.
- Achtergrond-daemons en onderhoud: We hebben al gesproken over de noodzaak van achtergrondprocessen om controlepunten te maken, back-ups te maken, logboeken bij te werken, afval te verzamelen en het opruimen van middelen af te handelen. Deze kunnen echter de prestaties van het systeem verminderen tijdens het uitvoeren. Om dit te verhelpen, is het belangrijk om de onderbrekingen door onderhoudsactiviteiten te synchroniseren om de impact op de verkeersstroom te minimaliseren. Dit zorgt ervoor dat alle variaties plaatsvinden in een kort, bekend venster in plaats van willekeurig gedurende de levensduur van de toepassing.
- wachtrijen: een andere veelvoorkomende bron van variabiliteit is de burstiness van verkeerskomstpatronen.1 Deze variabiliteit wordt verergerd als het besturingssysteem een ander planningsalgoritmen dan FIFO gebruikt. Linux-systemen plannen vaak threads in een andere volgorde om de totale prestaties te optimaliseren en het gebruik van de server te maximaliseren. Studies hebben vastgesteld dat het gebruik van FIFO-planning in het besturingssysteem de tail-latentie vermindert ten koste van de algehele doorvoer van het systeem.
- All-to-all incast: Het patroon dat in afbeelding 8 hierboven wordt weergegeven, wordt all-to-all-communicatie genoemd. Omdat de meeste netwerkcommunicatie via TCP verloopt, leidt dit tot duizenden gelijktijdige aanvragen en antwoorden tussen de front-endwebserver en alle back-endverwerkingsknooppunten. Dit is een extreem bursty patroon van communicatie en leidt vaak tot een speciale vorm van congestiefout, bekend als TCP incast collapse.1, 2 De intense plotselinge reactie van duizenden servers leidt tot veel verloren en opnieuw verzonden pakketten, wat uiteindelijk leidt tot een netwerkoverbelasting van verkeer voor pakketten met zeer kleine gegevens. Grote datacenters en cloudtoepassingen moeten vaak aangepaste netwerkstuurprogramma's gebruiken om het ontvangen TCP-venster en de timer voor hertransmissie dynamisch aan te passen. Routers kunnen ook worden geconfigureerd om verkeer te verminderen dat een specifieke snelheid overschrijdt en de grootte van het verzenden te verkleinen.
- energie- en temperatuurbeheer: ten slotte is variabiliteit een bijproduct van andere kostenreductietechnieken, zoals het gebruik van niet-actieve statussen of omlaag schalen van CPU-frequentie. Een processor kan vaak een niet-triviale hoeveelheid tijd besteden aan omhoog schalen vanuit een niet-actieve status. Het uitschakelen van dergelijke kostenoptimalisaties leidt tot een hoger energieverbruik en hogere kosten, maar lagere variabiliteit. Dit is minder een probleem in de openbare cloud, omdat prijsmodellen zelden rekening houden met metrische gegevens over intern gebruik van de resources van de klant.
Sommige experimenten hebben vastgesteld dat de variabiliteit van dergelijke systemen veel erger is in de openbare cloud,3 meestal vanwege onvolkomen prestatie-isolatie van virtuele resources en de gedeelde processor. Dit wordt verergerd als veel latentiegevoelige taken worden uitgevoerd op hetzelfde fysieke knooppunt als CPU-intensieve taken.
Leven met variabiliteit: Technische oplossingen
Veel van de bovenstaande bronnen van variabiliteit hebben geen onfeilbare oplossing. Daarom moeten cloudtoepassingen zijn ontworpen om staarttolerant te zijn in plaats van alle bronnen op te lossen die de latentiestaart opblazen. Dit is natuurlijk vergelijkbaar met de manier waarop we toepassingen ontwerpen die fouttolerant zijn, omdat we niet kunnen hopen om alle mogelijke fouten op te lossen. Enkele veelvoorkomende technieken om met deze variabiliteit om te gaan, zijn:
- 'Goed genoeg'-resultaten: wanneer het systeem wacht op het ontvangen van resultaten van duizenden knooppunten, wordt ervan uitgegaan dat het belang van één resultaat vrij laag is. Daarom kunnen veel toepassingen ervoor kiezen om eenvoudig te reageren op de gebruikers met resultaten die binnen een bepaald, kort latentievenster binnenkomen en de rest negeren.
- Canaries: Een ander alternatief dat vaak wordt gebruikt voor zeldzame codepaden, is het testen van een aanvraag op een kleine subset van leaf-knooppunten om te testen of dit een crash of storing veroorzaakt die van invloed kan zijn op het hele systeem. De volledige fan-out query wordt alleen gegenereerd als de canary geen fout veroorzaakt. Dit is vergelijkbaar met het verzenden van een kanarie (vogel) naar een kolenmijn om te testen of het veilig is voor mensen.
- Latentie-geïnduceerde proeftijd- en gezondheidscontroles: Natuurlijk is het merendeel van de aanvragen voor een systeem te alledaags om getest te worden met een kanarie-test. Dergelijke verzoeken hebben waarschijnlijk een lange staart als een van de bladknopen slecht presteert. Om dit tegen te gaan, moet het systeem periodiek de status en latentie van elk leaf-knooppunt bewaken en geen aanvragen routeren naar knooppunten die lage prestaties demonstreren (vanwege onderhoud of storingen).
- differentiële QoS-: afzonderlijke serviceklassen kunnen worden gemaakt voor interactieve aanvragen, zodat ze prioriteit kunnen hebben in elke wachtrij. Latentie-ongevoelige toepassingen kunnen langere wachttijden voor hun bewerkingen tolereren.
- aanvraag hedging: dit is een eenvoudige oplossing om de impact van variabiliteit te verminderen door dezelfde aanvraag door te sturen naar meerdere replica's en het antwoord te gebruiken dat het eerst binnenkomt. Dit kan natuurlijk de benodigde hoeveelheid resources verdubbelen of drie keer verdubbelen. Om het aantal afgehandelde verzoeken te verminderen, kan de tweede aanvraag alleen worden verzonden als het eerste antwoord in behandeling is gedurende meer dan het 95e percentiel van de verwachte latentie voor die aanvraag. Dit zorgt ervoor dat de extra belasting slechts ongeveer 5%is, maar de latentiestaart aanzienlijk vermindert (in het typische geval dat wordt weergegeven in afbeelding 9, waarbij de latentie van het 95e percentiel veel lager is dan de latentie van het 99e percentiel).
- Speculatieve uitvoering en selectieve replicatie: Taken op knooppunten die bijzonder druk zijn, kunnen speculatief worden gestart op andere onderbenutte bladerknooppunten. Dit is vooral effectief als een fout in een bepaald knooppunt ervoor zorgt dat het overbelast raakt.
- op UX gebaseerde oplossingen: Tot slot kan de vertraging intelligent worden verborgen voor de gebruiker via een goed ontworpen gebruikersinterface die het gevoel van vertraging vermindert die wordt ervaren door een menselijke gebruiker. Technieken om dit te doen kunnen het gebruik van animaties zijn, het weergeven van vroege resultaten of het betrekken van de gebruiker door relevante berichten te verzenden.
Met behulp van deze technieken is het mogelijk om de ervaring van eindgebruikers van een cloudtoepassing aanzienlijk te verbeteren om het eigenaardige probleem van een lange staart op te lossen.
Verwijzingen
- Li, J., Sharma, N. K., Ports, D. R., & Gribble, S. D. (2014). Verhalen van de Staart: Hardware, OS en Application-Level Bronnen van Staartlatentie uit de Proceedings van het ACM Symposium over Cloud Computing, ACM
- Wu, Haitao en Feng, Zhenqian en Guo, Chuanxiong en Zhang, Yongguang (2013). ICTCP: Incast Congestiebeheer voor TCP in Data-Center Networks, IEEE/ACM Transactions on Networking (TON), IEEE Press
- Xu, Yunjing, Musgrave, Zachary, Noble, Brian en Bailey, Michael (2013). Bobtail: Lange staarten vermijden in de cloud, 10e USENIX Conference on Networked Systems Design and Implementation, USENIX Association
- Dean, Jeffrey en Barroso, Luiz André (2013). De staart op schaal, Communications van de ACM, ACM
- Tene, Gil (2014). [Inzicht in latentie - Enkele belangrijke lessen en hulpprogramma's](https://www.infoq.com/presentations/latency-lessons-tools/, QCon London
Uw kennis controleren
Feedback
Is deze pagina nuttig?
No
Hulp nodig bij dit onderwerp?
Wilt u Ask Learn gebruiken om iets te verduidelijken of u door dit onderwerp te leiden?