[Oersetting] Envoy threading model

Oersetting fan it artikel: Envoy threading model - https://blog.envoyproxy.io/envoy-threading-model-a8d44b922310

Ik fûn dit artikel frij nijsgjirrich, en om't Envoy it meast brûkt wurdt as ûnderdiel fan 'e "istio" of gewoan as de "yngongskontrôler" fan kubernetes, hawwe de measte minsken net deselde direkte ynteraksje mei har as, bygelyks, mei typyske Nginx of Haproxy ynstallaasjes. As der lykwols wat brekt, soe it goed wêze om te begripen hoe't it fan binnen wurket. Ik besocht safolle mooglik fan 'e tekst yn it Russysk oer te setten, ynklusyf spesjale wurden; foar dyjingen dy't it pynlik fine om dit te sjen, liet ik de orizjinelen tusken heakjes. Wolkom by kat.

Technyske dokumintaasje op leech nivo foar de Envoy-koadebase is op it stuit frij sparse. Om dit te ferhelpen, bin ik fan plan om in searje blogposten te dwaan oer de ferskate subsystemen fan Envoy. Om't dit it earste artikel is, lit my asjebleaft witte wat jo tinke en wêryn jo miskien ynteressearje kinne yn takomstige artikels.

Ien fan 'e meast foarkommende technyske fragen dy't ik krij oer Envoy is it freegjen fan in beskriuwing op leech nivo fan it threadingmodel dat it brûkt. Yn dit berjocht sil ik beskriuwe hoe't Envoy ferbiningen yn kaart bringt oan threads, lykas ek it Thread Local Storage-systeem dat it yntern brûkt om koade mear parallel en hege prestaasjes te meitsjen.

Threading oersjoch

[Oersetting] Envoy threading model

Envoy brûkt trije ferskillende soarten streamen:

  • Foarnaamste: Dizze thread kontrolearret it opstarten en beëinigjen fan proses, alle ferwurking fan 'e XDS (xDiscovery Service) API, ynklusyf DNS, sûnenskontrôle, algemiene kluster- en runtimebehear, reset fan statistyk, administraasje en algemien prosesbehear - Linux-sinjalen. hot opnij starte, ensfh. bart yn dizze tried is asynchrone en "net-blokkearjend". Yn it algemien koördinearret de haadtried alle krityske funksjonaliteitsprosessen dy't gjin grutte hoemannichte CPU nedich binne om te rinnen. Dit makket it mooglik de measte kontrôle koade wurde skreaun as wie it ien threaded.
  • Wurkster: Standert makket Envoy in worker thread foar elke hardware thread yn it systeem, dit kin wurde regele mei de opsje --concurrency. Elke wurktried rint in "net-blokkearjende" barren-loop, dy't ferantwurdlik is foar it harkjen nei elke harker; op it momint fan skriuwen (29 july 2017) is d'r gjin skuorre fan 'e harker, it akseptearjen fan nije ferbiningen, instânsje in filterstapel foar de ferbining, en it ferwurkjen fan alle ynfier / útfier (IO) operaasjes yn it libben fan de ferbining. Nochris lit dit de measte ferbiningshannelingskoade skreaun wurde as soe it ien thread wêze.
  • File Flusher: Elk bestân dat Envoy skriuwt, benammen tagongslogboeken, hat op it stuit in ûnôfhinklike blokkearjende tried. Dit is te tankjen oan it feit dat skriuwen nei bestannen yn 'e cache troch it bestânsysteem sels by it brûken O_NONBLOCK kin soms blokkearre wurde (sucht). As wurktrieden moatte skriuwe nei in bestân, wurde de gegevens feitlik ferpleatst nei in buffer yn it ûnthâld wêr't se úteinlik troch de tried spoeld wurde triem flush. Dit is ien gebiet fan koade wêr't technysk alle wurkthreads itselde slot kinne blokkearje by it besykjen om in ûnthâldbuffer te foljen.

Ferbining ôfhanneling

Lykas hjirboppe koart besprutsen, harkje alle wurktrieden nei alle harkers sûnder skea. Sa wurdt de kernel brûkt om sierlik akseptearre sockets te stjoeren nei arbeidersthreads. Moderne kernels binne oer it algemien heul goed yn dit, se brûke funksjes lykas ynput/útfier (IO) prioriteitsferbettering om te besykjen in thread te foljen mei wurk foardat se begjinne mei it brûken fan oare triedden dy't ek op deselde socket harkje, en ek gjin round robin brûke locking (Spinlock) te ferwurkjen elk fersyk.
Sadree't in ferbining wurdt akseptearre op in arbeider thread, it nea ferlit dy tried. Alle fierdere ferwurking fan 'e ferbining wurdt folslein yn' e wurktried behannele, ynklusyf alle trochstjoergedrach.

Dit hat ferskate wichtige gefolgen:

  • Alle ferbining pools yn Envoy wurde tawiisd oan in arbeider thread. Dat, hoewol HTTP / 2-ferbiningpools mar ien ferbining meitsje mei elke streamop-host tagelyk, as d'r fjouwer arbeidersthreads binne, sille d'r fjouwer HTTP / 2-ferbiningen per streamop-host wêze yn in fêste steat.
  • De reden dat Envoy op dizze manier wurket is dat troch alles op ien wurktried te hâlden, hast alle koade kin wurde skreaun sûnder blokkearjen en as soe it ien thread wêze. Dit ûntwerp makket it maklik om in protte koade te skriuwen en skaal ongelooflijk goed nei in hast ûnbeheind oantal arbeidersthreads.
  • Ien fan 'e wichtichste takeaways is lykwols dat it út in ûnthâldpool en ferbiningseffektiviteitsstandpunt eins heul wichtich is om de --concurrency. It hawwen fan mear worker threads dan nedich sil fergrieme ûnthâld, meitsje mear idle ferbinings, en ferminderjen it taryf fan ferbining pooling. By Lyft rinne ús konteners fan ús gesant foar sidecars mei in heul lege gearkomst, sadat de prestaasjes sawat oerienkomme mei de tsjinsten wêr't se neist sitte. Wy rinne Envoy as râneproxy allinich by maksimale gearhing.

Wat betsjut net-blokkearjen?

De term "net-blokkearjend" is oant no ta ferskate kearen brûkt by it besprekken fan hoe't de haad- en arbeidersthreads wurkje. Alle koade is skreaun op de oanname dat neat is oait blokkearre. Dit is lykwols net hielendal wier (wat is net hielendal wier?).

Envoy brûkt ferskate lange prosesslûzen:

  • Lykas besprutsen, by it skriuwen fan tagongslogboeken, krije alle wurktrieden deselde slûs foardat de logbuffer yn it ûnthâld is fol. It slot holding tiid moat wêze hiel leech, mar it is mooglik dat it slot wurdt bestriden op hege concurrency en hege trochset.
  • Envoy brûkt in heul kompleks systeem om statistiken te behanneljen dy't lokaal binne foar de thread. Dit sil it ûnderwerp wêze fan in aparte post. Ik sil lykwols koart neame dat as ûnderdiel fan it lokaal ferwurkjen fan threadstatistiken, it soms nedich is om in slot te krijen op in sintrale "statistike winkel". Dit beskoatteljen soe nea nedich wêze.
  • De haadtried moat periodyk koördinearje mei alle wurktrieden. Dit wurdt dien troch "publisearjen" fan 'e haadtried nei wurktrieden, en soms fan wurktrieden werom nei de haadtried. It ferstjoeren fereasket in slot sadat it publisearre berjocht yn wachtrige wurde kin foar lettere levering. Dizze slûzen moatte nea serieus bestriden wurde, mar se kinne noch technysk wurde blokkearre.
  • As Envoy skriuwt in log nei it systeem flater stream (standert flater), it krijt in slot op it hiele proses. Yn 't algemien wurdt de lokale logging fan Envoy as ferskriklik beskôge út in prestaasjestandpunt, dus d'r is net folle oandacht jûn oan it ferbetterjen.
  • Der binne in pear oare willekeurige slûzen, mar net ien fan harren is prestaasje kritysk en moat nea wurde útdage.

Thread lokale opslach

Fanwegen de manier wêrop Envoy de ferantwurdlikheden fan 'e haadtried skiedt fan' e ferantwurdlikheden fan 'e arbeidersdraad, is d'r in eask dat komplekse ferwurking kin wurde dien op 'e haadtried en dan op in heul simultane manier oan elke wurktried oanbean. Dizze paragraaf beskriuwt Envoy Thread Local Storage (TLS) op in heech nivo. Yn 'e folgjende paragraaf sil ik beskriuwe hoe't it wurdt brûkt om in kluster te behearjen.
[Oersetting] Envoy threading model

Lykas al beskreaun, behannelet de haadthread praktysk alle funksjonaliteit fan behear en kontrôlefleanmasine yn it Envoy-proses. It kontrôlefleantúch is hjir in bytsje oerladen, mar as jo it binnen it Envoy-proses sels sjogge en it fergelykje mei de trochstjoering dy't de worker threads dogge, makket it sin. De algemiene regel is dat it haadtriedproses wat wurk docht, en dan moat it elke arbeidersdraad bywurkje neffens it resultaat fan dat wurk. yn dit gefal, de arbeider tried net nedich te krijen in slot op eltse tagong.

Envoy's TLS (Thread lokale opslach) systeem wurket as folget:

  • Koade dy't rint op 'e haadtried kin in TLS-slot tawize foar it heule proses. Hoewol't dit is abstrahearre, yn 'e praktyk is it in yndeks yn in vector, jaan O (1) tagong.
  • De haadtried kin willekeurige gegevens yn har slot ynstallearje. As dit dien is, wurde de gegevens publisearre oan elke arbeidersdraad as in normaal barren foar eveneminten.
  • Worker threads kinne lêze út harren TLS slot en ophelje alle thread-lokale gegevens beskikber dêr.

Hoewol it in heul ienfâldich en ongelooflijk krêftich paradigma is, is it heul gelyk oan it konsept fan blokkearjen fan RCU (Read-Copy-Update). Yn essinsje sjogge wurktrieden noait gegevensferoarings yn 'e TLS-slots wylst it wurk rint. Feroaring komt allinich yn 'e rêstperioade tusken wurkeveneminten.

Envoy brûkt dit op twa ferskillende manieren:

  • Troch ferskate gegevens op elke wurktried op te slaan, kinne de gegevens tagonklik wurde sûnder blokkearjen.
  • Troch it behâld fan in dielde oanwizer nei globale gegevens yn allinnich-lêzen modus op elke arbeider thread. Sa hat elke wurktried in gegevensferwizingstelling dy't net kin wurde fermindere wylst it wurk rint. Allinich as alle arbeiders kalmearje en nije dielde gegevens uploade, wurde de âlde gegevens ferneatige. Dit is identyk oan RCU.

Cluster update threading

Yn dizze seksje sil ik beskriuwe hoe't TLS (Thread lokale opslach) wurdt brûkt om in kluster te behearjen. Klusterbehear omfettet xDS API en / of DNS-ferwurking, lykas sûnenskontrôle.
[Oersetting] Envoy threading model

Clusterflowbehear omfettet de folgjende komponinten en stappen:

  1. De Cluster Manager is in komponint binnen Envoy dy't alle bekende klusterupstreams beheart, de Cluster Discovery Service (CDS) API, de Secret Discovery Service (SDS) en Endpoint Discovery Service (EDS) API's, DNS, en aktive eksterne kontrôles. It is ferantwurdlik foar it meitsjen fan in "úteinlik konsekwint" werjefte fan elke streamop kluster, dy't ûntdutsen hosts omfettet lykas sûnensstatus.
  2. De sûnenskontrôler fiert in aktive sûnenskontrôle út en rapporteart feroaringen fan sûnensstatus oan de klusterbehearder.
  3. CDS (Cluster Discovery Service) / SDS (Secret Discovery Service) / EDS (Endpoint Discovery Service) / DNS wurde útfierd om klusterlidmaatskip te bepalen. De steatferoaring wurdt weromjûn oan de klusterbehearder.
  4. Elke worker thread fiert kontinu in evenemintloop út.
  5. As de klusterbehearder bepaalt dat de tastân foar in kluster feroare is, makket it in nije lês-allinich momintopname fan 'e steat fan it kluster en stjoert it nei elke wurktried.
  6. Tidens de folgjende stille perioade sil de wurktried de momintopname bywurkje yn it tawiisde TLS-slot.
  7. Tidens in I/O-evenemint dat de host moat bepale om lykwicht te laden, sil de loadbalancer in TLS (Thread local storage) slot freegje om ynformaasje oer de host te krijen. Dit hat gjin sloten nedich. Tink derom ek dat TLS ek update-eveneminten kin triggerje, sadat loadbalancers en oare komponinten caches, gegevensstruktueren, ensfh. Dit is bûten it berik fan dizze post, mar wurdt brûkt op ferskate plakken yn 'e koade.

Mei de boppesteande proseduere kin Envoy elk fersyk ferwurkje sûnder blokkearjen (útsein lykas earder beskreaun). Njonken de kompleksiteit fan 'e TLS-koade sels, hoecht de measte fan' e koade net te begripen hoe't multithreading wurket en kin wurde skreaun single-threaded. Dit makket it measte fan 'e koade makliker te skriuwen neist superieure prestaasjes.

Oare subsystemen dy't gebrûk meitsje fan TLS

TLS (Thread lokale opslach) en RCU (Read Copy Update) wurde breed brûkt yn Envoy.

Foarbylden fan gebrûk:

  • Mechanisme foar it feroarjen fan funksjonaliteit by útfiering: De hjoeddeistige list mei ynskeakele funksjonaliteit wurdt berekkene yn 'e haadthread. Elke worker thread wurdt dan in lês-allinich snapshot jûn mei RCU-semantyk.
  • It ferfangen fan rûte tabellen: Foar rûtetabellen fersoarge troch RDS (Route Discovery Service), wurde de rûtetabellen makke op 'e haadtried. De read-allinnich snapshot sil dêrnei wurde levere oan elke arbeider thread mei RCU (Read Copy Update) semantyk. Dit makket feroarjende rûte tabellen atomically effisjint.
  • HTTP header caching: As it docht bliken, is it berekkenjen fan de HTTP-header foar elk fersyk (by it útfieren fan ~25K + RPS per kearn) frij djoer. Envoy berekkent sintraal de koptekst sawat elke heale sekonde en leveret it oan elke arbeider fia TLS en RCU.

D'r binne oare gefallen, mar de foarige foarbylden moatte in goed begryp jaan fan wêr't TLS foar brûkt wurdt.

Bekende prestaasjes pitfalls

Wylst Envoy yn 't algemien frij goed presteart, binne d'r in pear opmerklike gebieten dy't oandacht fereaskje as it wurdt brûkt mei heul hege tagelyk en trochset:

  • Lykas beskreaun yn dit artikel, krije op it stuit alle wurktrieden in slot by it skriuwen nei de buffer foar tagongsloggeheugen. By hege concurrency en hege trochset moatte jo de tagongslogboeken foar elke arbeidersdraad batchje op kosten fan levering sûnder bestelling by it skriuwen nei it definitive bestân. As alternatyf kinne jo in apart tagongslogboek meitsje foar elke wurktried.
  • Hoewol de statistiken heul optimalisearre binne, sil d'r by heul hege gearkomst en trochset wierskynlik atomêre konflikt wêze oer yndividuele statistiken. De oplossing foar dit probleem is tellers per worker thread mei periodike reset fan sintrale tellers. Dit sil wurde besprutsen yn in folgjende post.
  • De hjoeddeistige arsjitektuer sil net goed wurkje as Envoy wurdt ynset yn in senario wêr't d'r heul pear ferbiningen binne dy't wichtige ferwurkingsboarnen nedich binne. D'r is gjin garânsje dat ferbinings lykwichtich ferdield wurde ûnder arbeidersthreads. Dit kin wurde oplost troch it útfieren fan balânsjen fan arbeidersferbining, wêrtroch de útwikseling fan ferbiningen tusken arbeidersthreads mooglik makket.

Konklúzje

It threadingmodel fan Envoy is ûntworpen om maklik te programmearjen en massaal parallelisme te leverjen ten koste fan potensjeel fergriemd ûnthâld en ferbiningen as net goed konfigureare. Dit model lit it heul goed prestearje by heul hege thread-tellingen en trochset.
Lykas ik koart op Twitter neamde, kin it ûntwerp ek rinne boppe op in folsleine brûkersmodus netwurkstapel lykas DPDK (Data Plane Development Kit), wat kin resultearje yn konvinsjonele tsjinners dy't miljoenen oanfragen per sekonde behannelje mei folsleine L7-ferwurking. It sil tige nijsgjirrich wêze om te sjen wat der yn de kommende jierren boud wurdt.
Ien lêste rappe opmerking: ik bin in protte kearen frege wêrom't wy C++ foar Envoy keas. De reden bliuwt dat it noch altyd de iennichste breed brûkte yndustriële graadtaal is wêryn't de arsjitektuer beskreaun yn dizze post boud wurde kin. C++ is perfoarst net geskikt foar alle of sels in protte projekten, mar foar bepaalde gebrûksgefallen is it noch altyd it ienige ark om it wurk dien te krijen.

Keppelings nei koade

Keppelings nei bestannen mei ynterfaces en koptekstimplementaasjes besprutsen yn dizze post:

Boarne: www.habr.com

Add a comment