Artikli tÔlge:
See artikkel tundus mulle ĂŒsna huvitav, kuna Envoyd kasutatakse kĂ”ige sagedamini osana 'istio'st' vĂ”i lihtsalt kui 'ingress controller' kubernetes'is, seega ei puutu enamik inimesi sellega sama otseselt kokku kui nĂ€iteks tavaliste Nginxi vĂ”i Haproxy installatsioonidega. Kuid kui midagi katki lĂ€heb, oleks hea mĂ”ista, kuidas see seestpoolt töötab. Olen pĂŒĂŒdnud tĂ”lkida nii palju sisu vene keelde, kui vĂ”imalik, sealhulgas erilise sĂ”navara jaoks, ning kellele selline asi ei meeldi, olen originaalid sulgudes jĂ€tnud. Tere tulemast lĂ”ppu.
Envoy koodibaasi madala taseme tehniline dokumentatsioon on praegu ĂŒsna napp. Selle parandamiseks plaanin teha seeria blogipostitusi erinevatest Envoy alamsĂŒsteemidest. Kuna see on esimene artikkel, andke mulle teada, mida te arvate ja mis vĂ”iks jĂ€rgmistes artiklites huvitav olla.
Ăks levinumaid tehnilisi kĂŒsimusi, mida ma Envoy kohta saan, on madala taseme kirjelduse kĂŒsimine kasutatavast lĂ”imemudelist (threading model). Selles postituses kirjeldan, kuidas Envoy seob ĂŒhendused lĂ”imedele, samuti sĂŒsteemi kohalikku lĂ”imede salvestust (Thread Local Storage), mida kasutatakse sees, et muuta kood paralleelsemaks ja suurema jĂ”udlusega.
LÔimede kirjeldus (Threading overview)
![[TÔlge] Envoy mudelide voogude (Envoy threading model)](/wp-content/uploads/2019/04/c5028463db1eb5b07ccb1a3af1f64a03.jpeg)
Envoy kasutab kolme erinevat tĂŒĂŒpi lĂ”ime:
- Peamine (Main): See lĂ”im haldab protsessi kĂ€ivitamist ja lĂ”petamist, kogu XDS (xDiscovery Service) API töötlemist, sealhulgas DNS-i, tervisekontrolli (health checking), klastrihalduse ja teenuse tööprotsessi (runtime), statistika lĂ€htestamist, haldust ja ĂŒldist protsesside haldust â Linuxi signaalid, kuum kĂ€ivitamine (hot restart) jne. KĂ”ik, mis selles lĂ”imes toimub, on asĂŒnkrooniline ja 'mitteblokeeriv'. Ăldiselt koordineerib peamine lĂ”im kĂ”ik kriitilised funktsionaalsuse protsessid, milleks ei ole vajalik suur hulk CPU-d. See vĂ”imaldab enamiku halduskoode kirjutada nii, nagu oleks see ĂŒhesĂŒsteemne.
- Töötaja (Worker): Vaikimisi loob Envoy töötava lĂ”ime (worker thread) iga sĂŒsteemi riistvaralise lĂ”ime jaoks, mida saab kontrollida valiku abil
--concurrency. Iga töövoog kĂ€ivitab "mitteblokeeriva" sĂŒndmuste tsĂŒkli (event loop), mis vastutab iga kuulaja (listener) jĂ€lgimise eest. Artikli kirjutamise ajal (29. juuli 2017) ei ole kuulaja (listener) segmenteerimist (sharding), uute ĂŒhenduste vastuvĂ”tmine, filtrite virna loomine ĂŒhenduse loomiseks ja kĂ”ik sisend-vĂ€ljundi (IO) toimingute töötlemine ĂŒhenduse eksisteerimise ajal. Taaskord vĂ”imaldab see kirjutada suure osa ĂŒhenduste töötlemise koodist nagu see oleks ĂŒhesuunaline. - Faili (File flusher): Iga fail, mida Envoy kirjutab, peamiselt juurdepÀÀsu logid (access logs), omab praegu sĂ”ltumatut blokeerivat töövoogu. See on tingitud asjaolust, et kirjutamine failidesse, mis on vahemĂ€lus failisĂŒsteemi poolt, isegi O_NONBLOCK kasutamisel
O_NONBLOCKvĂ”ib mĂ”nikord blokeerida (ahh). Kui töövoogudel on vaja faili kirjutada, liigutatakse andmed tegelikult mĂ€lu bufrisse, kus need lĂ”puks tĂ”ukatakse lĂ€bi file flush. See on ĂŒks koodivaldkondi, kus tehniliselt vĂ”ivad kĂ”ik töövood (worker threads) blokeerida (block) sama lukku (lock), pĂŒĂŒdes mĂ€lu bufrisse tĂ€ituda.
Ăhenduste töötlemine (Connection handling)
Kuidas arutleti lĂŒhidalt eespool, kuulevad kĂ”ik töövood kĂ”iki kuulajaid (listeners) ilma igasuguse segmenteerimiseta. Seega kasutatakse tuuma goed Ă”ige socketâitega töötlemiseks töövoogude vahel. Kaasaegsed tuumad on selles osas ĂŒsna head, nad kasutavad selliseid funktsioone nagu sisendi/vĂ€ljundi (IO) prioriteedi tĂ”stmine, et pĂŒĂŒda tĂ€ita voogu enne, kui nad hakkavad kasutama teisi vooge, mis kuulavad ka sama socketâit, ja samuti mitte kasutada tsĂŒklit lukustumiseks (Spinlock) iga pĂ€ringu töötlemiseks.
Kuna ĂŒhendus on töövoo (worker thread) poolt vastu vĂ”etud, ei lahku see kunagi sellest voost (thread). KĂ”ik edasine ĂŒhenduse töötlemine toimub tĂ€ielikult töövoos (worker thread), sealhulgas mis tahes edasi suunamise kĂ€itumine (forwarding behavior).
Sel on mitu olulist tagajÀrge:
- KĂ”ik Envoy ĂŒhenduste basseinid kuuluvad töövoogude hulka. SeetĂ”ttu, kuigi HTTP/2 ĂŒhenduste basseinid loovad iga ĂŒlesvoolu hostiga korraga vaid ĂŒhe ĂŒhenduse, on neli töövoogu korral neli HTTP/2 ĂŒhendust ĂŒlesvoolu hostiga stabiilses olekus.
- PĂ”hjus, miks Envoy nii töötab, on see, et hoides kĂ”ik ĂŒhes töövoos, saab enamus koodist kirjutada ilma lukustusteta ja nagu ĂŒhesuunaline. See disain lihtsustab suure koodi kirjutamist ja skaleerub uskumatult hĂ€sti praktiliselt piiramatu arvu töövoogude jaoks.
- Kuid ĂŒks peamisi jĂ€reldusi on see, et mĂ€lu- ja ĂŒhenduste basseinide efektiivsuse seisukohalt on tĂ”eliselt oluline konfigureerida parameeter
--concurrency. Liigne töövoogude arv toob kaasa mĂ€lu raiskamise, suure hulga passiivsete ĂŒhenduste tekkimise ja ĂŒhenduste basaeni sisenemise kiirus vĂ€heneb. Lyftis töötavad meie Envoy sidecar konteinerid vĂ€ga madala paralleelsuse juures, nii et jĂ”udlus vastab umbes nende teenuste tasemele, mille kĂ”rval nad asuvad. KĂ€ivitame Envoy piiriprotokollina (edge) ainult maksimaalse paralleelsuse korral.
Mida tĂ€hendab mitte-blokeeriv reĆŸiim (What non-blocking means)
Termin 'mitte-blokeeriv' on kuni nĂŒĂŒd korduvalt kasutatud arutades, kuidas töötavad pĂ”hivoog ja töövood. Kogu kood on kirjutatud eeldusel, et miski ei blokeeru kunagi. Kuid see ei ole tĂ€iesti tĂ”si (mis ei ole tĂ€iesti tĂ”si?).
Envoy kasutab mitmeid pikaajalisi protsessi lukustusi:
- Nagu varem mainitud, saavad kÔik töövood juurdepÀÀsulogide kirjutamise ajal sama lukustuse enne mÀlus logifaili puhverdamist. Lukustuse hoidmise aeg peaks olema vÀga madal, kuid on vÔimalik, et see lukustus vaidlustatakse kÔrge paralleelsuse ja kÔrge lÀbilaskevÔime korral.
- Envoy kasutab voogude statistika töötlemiseks vĂ€ga keerulist sĂŒsteemi, mis on voogudele lokaalset. See on eraldi postituse teema. Siiski mainin lĂŒhidalt, et lokaalse statistika töötlemise osana on mĂ”nikord vajalik keskse 'statistikalao' lukustamine. Seda lukustamist ei tohiks kunagi nĂ”uda.
- Peavoo vajab perioodiliselt koordineerimist kÔigi töövoogudega. Seda tehakse, 'publitseerides' peavoo sÔnumid töövoogudele ja mÔnikord ka töövoogudest tagasi peavoo. SÔnumi saatmiseks on vajalik lukustus, et avaldatud sÔnum saaks jÀrjekorda panna edasise kohaletoimetamise jaoks. Need lukustused ei tohiks kunagi olla tÔsise konkurentsi all, kuid need vÔivad siiski tehniliselt saada blokeeritud.
- Kui Envoy kirjutab logi sĂŒsteemi veavoo (standard error), siis sellel on blokeering kogu protsessis. Ăldiselt peetakse Envoy lokaalset logimist jĂ”udluse seisukohast kohutavaks, seega ei pöörata selle parandamisele palju tĂ€helepanu.
- On mĂ”ned muud juhuslikud lukustused, kuid ĂŒkski neist ei ole kriitiline jĂ”udluse jaoks ja neid ei tohiks kunagi vaidlustada.
Thread local storage (voo lokaalne salvestus)
Kuna Envoy eristab peavoo ja töövoogude kohustusi, on nĂ”udmine, et keeruline töötlemine vĂ”iks toimuda peavoo kaudu ja seejĂ€rel jagada seda kĂ”rge paralleelsusega igale töövoole. Selles jaotises on kĂ”rgel tasemel kirjeldatud Envoy Thread Local Storage (TLS) sĂŒsteemi. JĂ€rgmises jaotises kirjeldan, kuidas seda kasutatakse klastrihalduseks.
![[TÔlge] Envoy mudelide voogude (Envoy threading model)](/wp-content/uploads/2019/04/a47af1e8eb1f55a4d7609b3ff3ee9ce1.jpeg)
Kuna juba mainitud, tegeleb peavoo praktiliselt kĂ”igi haldusfunktsioonide ja juhtimistasandi funktsionaalsusega Envoy protsessis. Juhtimistasand on siin natuke ĂŒlekoormatud, kuid kui vaadata seda itse Envoy protsessi kontekstis ja vĂ”rrelda töövoogude edastamisega, tundub see mĂ”istlik. Ăldiselt tĂ€idab peavoo mĂ”ningaid ĂŒlesandeid ja seejĂ€rel tuleb igat töövoogu uuendada vastavalt nende töö tulemustele. samal ajal ei pea töösuuna iga juurdepÀÀsu korral lukustust seadma.
TLS (Thread local storage) sĂŒsteem Envoy toimib jĂ€rgmiselt:
- Kood, mis töötab pÔhijuhtmes, vÔib eraldada TLS-slotid kogu protsessi jaoks. Kuigi see on abstraktne, on praktikas tegemist indeksiga vektorisse, mis tagab O(1) juurdepÀÀsu.
- PĂ”hijuhtme korral vĂ”ib see seada suvalisi andmeid oma slotis. Kui see on tehtud, avaldatakse andmed iga töösuuna puhul tavalise sĂŒndmuste tsĂŒkli sĂŒndmusena.
- Töösuunad saavad lugeda oma TLS-slotist ja vÀlja vÔtta seal saadaval olevaid kohalikke andmeid.
Kuigi see on vĂ€ga lihtne ja ÀÀrmiselt vĂ”imas paradigma, mis on vĂ€ga sarnane RCU (Read-Copy-Update) lukustuse kontseptsioonile. Essentsiaalselt ei nĂ€e töösuunad töö kĂ€igus sloti TLS andmete muudatusi. Muudatus toimub ainult rahuperioodil töö sĂŒndmuste vahel.
Envoy kasutab seda kahel erineval viisil:
- Hoides erinevaid andmeid igas töösuunas, tagatakse nendele andmetele juurdepÀÀs ilma mingisuguse lukustamiseta.
- Hoides igas töösuunas ĂŒldist nĂ€idikut globaalsetele andmetele, mis on âainult lugemiseks.â Seega on igal töösuunal viidatud andmete viidatud loenduri, mida ei saa töö kĂ€igus vĂ€hendada. Ainult kui kĂ”ik töötajad rahunevad ja laadivad uusi ĂŒldisi andmeid, hĂ€vitatakse vanad andmed. See on identne RCU-ga.
Klastri vÀrskendamise protsess
Selles osas kirjeldan, kuidas TLS (Thread local storage) kasutatakse klastri haldamiseks. Klastri haldamine hÔlmab API xDS ja / vÔi DNS töötlemist, samuti tervise kontrollimist.
![[TÔlge] Envoy mudelide voogude (Envoy threading model)](/wp-content/uploads/2019/04/238f5718729e1f12f8f0d6507f16abe8.jpeg)
Klastri töösuunade haldamine hÔlmab jÀrgmisi komponente ja etappe:
- Klastri haldaja on komponent, mis asub Envoy sees, ja see haldab kĂ”iki tuntud klastri upstream'e, CDS (Cluster Discovery Service) API, SDS (Secret Discovery Service) ja EDS (Endpoint Discovery Service) API-sid, DNS-i ning aktiivseid vĂ€liseid tervise kontrollimise protsesse. See vastutab iga klastri upstreami âlĂ”puks jĂ€rjekindlaâ (eventually consistent) arusaama loomise eest, mis hĂ”lmab avastatud hoste ja tervise staatust.
- Tööoleku kontrollimise tööriist (health checker) teeb aktiivset tööoleku kontrolli ja teatab tööoleku muutustest klastrihaldurile.
- CDS (Cluster Discovery Service) / SDS (Secret Discovery Service) / EDS (Endpoint Discovery Service) / DNS kasutatakse klastrisse kuuluvuse mÀÀramiseks. Oleku muutus edastatakse klastrihaldurile.
- Iga töövoog tĂ€idab pidevalt sĂŒndmuste töötlemise tsĂŒklit.
- Kui klastrihaldur mÀÀrab, et klastrite olek on muutunud, loob ta klastrite uut oleku snapshots, mis on ainult lugemiseks ja saadab selle igasse töövoogu.
- JÀrgneva puhkuste jooksul uuendab töövoog snapshots eraldatud TLS-slottis.
- Sisend / vĂ€ljund sĂŒndmuse ajal, mis peaks mÀÀrama koormuse tasakaalustamiseks hosti, kĂŒsib tasakaalustaja TLS-slotist (Thread local storage) hosti teavet. Selleks ei nĂ”uta lukustusi. Samuti on oluline mĂ€rkida, et TLS vĂ”ib ka algatada sĂŒndmusi uuendamisel, et koormuse tasakaalustamise sĂŒsteemid ja muud komponendid saaksid arvutada uuesti vahemĂ€lud, andmestruktuurid jne. See ĂŒletab selle postituse ulatuse, kuid on kasutuses mitmetes koha koodis.
Kasutades ĂŒlaltoodud protseduuri, suudab Envoy igat pĂ€ringut kĂ€sitleda ilma lukustusteta (vĂ€lja arvatud eelnevalt kirjeldatud). Lisaks TLS-i koodi keerukusele ei pea enamik koodist mĂ”istma, kuidas korraga töötamine töötab, ja selle vĂ”ib kirjutada ĂŒhesuunalist reĆŸiimi. See lihtsustab suure osa koodi kirjutamist ja tagab suurepĂ€rase jĂ”udluse.
Teised subsĂŒsteemid, mis kasutavad TLS
TLS (Thread local storage) ja RCU (Read Copy Update) on laialdaselt kasutusel Envoy-s.
Kasutuse nÀited:
- Jooksvate funktsioonide muutmise mehhanism: KÀimasolev funktsionaalsuse loend arvutatakse pÔhivoos. Siis antakse igale töövoole lugemiseks ainult snapshot, kasutades RCU semantikat.
- Marƥrutustabelite asendamine: marsruutide tabelite jaoks, mida pakub RDS (Route Discovery Service), luuakse marsruutide tabelid peavoolus. Edasi antakse iga töösuuna jaoks ainult lugemiseks mÔeldud koopia, kasutades RCU (Read Copy Update) semantikat. See muudab marsruutide tabelite muutmise aatomiliselt efektiivseks.
- HTTP pĂ€iste vahemĂ€lu: Kuidas selgub, on iga pĂ€ringu HTTP pĂ€ise arvutamine (kui teostatakse ~25K+ RPS tuuma kohta) ĂŒsna kulukas. Envoy arvutab pĂ€ise tsentraalselt umbkaudu iga poole sekundi tagant ja edastab selle igale töötajale lĂ€bi TLS ja RCU.
On ka teisi juhtumeid, kuid eelnevad nÀited peaksid andma hea arusaama, milleks kasutatakse TLS-i.
Tuntud jÔudlusprobleemid (Known performance pitfalls)
Kuigi Envoy töötab ĂŒldiselt hĂ€sti, on mĂ”ned tuntud valdkonnad, mis vajavad tĂ€helepanu, kui seda kasutatakse vĂ€ga kĂ”rge samasuse ja lĂ€bilaskevĂ”imega:
- Nagu kÀesolevas artiklis on juba kirjeldatud, saavad kÔik töötajate vood kirjutamise ajal ligipÀÀsu logi vahemÀlule lukustatud. Suure samasuse ja kÔrge lÀbilaskevÔime korral on vajalik ligipÀÀsu logide paketiseerimine iga töövoo jaoks, mis saavutatakse lÔppfaili kirjutamise juures mittejÀrjekindla kohaletoimetamisega. Alternatiivina on vÔimalik luua igale töövoole eraldi ligipÀÀsu logi.
- Kuigi statistika on vĂ€ga optimeeritud, on vĂ€ga kĂ”rge samasuse ja lĂ€bilaskevĂ”ime korral tĂ”enĂ€oliselt aatomiline konkurents individuaalse statistika osas. Selle probleemi lahendamiseks on soovitatavad ĂŒhe töövoo loenduriga periodilised keskmised loendurid. Seda arutatakse jĂ€rgmises postituses.
- Olemasolev arhitektuur ei tööta hĂ€sti, kui Envoy on juurutatud stsenaariumis, kus on vĂ€ga vĂ€he ĂŒhendusi, mis nĂ”uavad intensiivset ressursside töötlemist. Pole garanteeritud, et ĂŒhendused jaotuvad töötajate voogude vahel ĂŒhtlaselt. Seda on vĂ”imalik lahendada tööde ĂŒhenduste tasakaalustamisega, rakendades ĂŒhenduste vahetamise vĂ”imalust töövoogude vahel.
KokkuvÔte (Conclusion)
Envoy voogemudel on loodud programmeerimise ja massilise paralleelsuse lihtsustamiseks, potentsiaalselt raiskavale mĂ€lule ja ĂŒhendustele, kui neid ei konfigureerita Ă”igesti. See mudel vĂ”imaldab tal vĂ€ga hĂ€sti töötada vĂ€ga kĂ”rge voogude ja lĂ€bilaskevĂ”ime korral.
Nagu ma lĂŒhidalt Twitteris mainisin, vĂ”ib disain töötada ka tĂ€isfunktsionaalse vĂ”rgu stack'i peal kasutaja reĆŸiimis, nĂ€iteks DPDK (Data Plane Development Kit), mis vĂ”ib viia selleni, et tavased serverid töötlevad miljonite pĂ€ringute sekundis tĂ€ieliku L7 töötlemise juures. Oleme vĂ€ga huvitatud nĂ€gema, mis jĂ€rgmise paariaasta jooksul saab ehitatud.
Viimane kiire kommentaar: olen korduvalt kĂŒsinud, miks me valisime C ++ Envoy jaoks. PĂ”hjus on endiselt see, et see on ainus laialdaselt levinud tööstuslik tase keel, millega saab ehitada arhitektuuri, millest selles postituses rÀÀkisime. C ++ ei sobi kindlasti kĂ”igile vĂ”i isegi paljudele projektidele, kuid teatud kasutusjuhtumite jaoks on see endiselt ainus tööriist töö tegemiseks.
Koodilingid (Links to code)
LingidFailide kohta, mille liideste ja rakenduste pealkirjad selles postituses arutatakse:
Allikas: habr.com
