Principi i paqartësisë i Heisenbergut thotë se nuk është e mundur të matin ngjashëm pozita dhe shpejtësinë e një objekti. Nëse objekti është në lëvizje, atëherë ai nuk ka një vendndodhje të saktë. Ndërsa, nëse ka një vendndodhje, atëherë nuk ka shpejtësi.

Sa i përket mikroshërbimeve mbi platformën Red Hat OpenShift (nën menaxhimin e Kubernetes), përmes softuerit përkatës me burim të hapur, ato mund të raportojnë njëkohësisht për performancën dhe gjendjen e tyre. Kjo nuk e mohon teorinë e Heisenbergut, por ndihmon në eleminimin e paqartësisë gjatë punës me aplikacionet cloud. Istio lejon organizimin e lehtë të gjurmimit dhe monitorimit të këtyre aplikacioneve, për të mbajtur gjithçka nën kontroll.
Përcaktojmë terminologjinë
Nën gjurmimit (Tracing) ne kuptojmë si regjistrimin e aktivitetit të sistemit. Kjo tingëllon mjaft e përgjithshme, por në të vërtetë një nga rregullat kryesore këtu është që të dërgosh të dhënat e gjurmimit në një depo të përshtatshme, pa u shqetësuar për formatimin e tyre. Të gjitha punët për gjetjen dhe analizimin e të dhënave janë ngarkuar te përdoruesi i tyre. Në Istio përdoret sistemi i gjurmimit Jaeger, i cili realizon modelin e të dhënave OpenTracing.
Gjurmët (Traces, dhe fjala "gjurmët" përdoret këtu në kuptimin e "shenjave", si për shembull në ekspertizën ballistike) ne do t'i referohemi të dhënave që përshkruajnë plotësisht kalimin e një kërkese ose njësi pune, siç thotë shprehja "nga fillimi deri në fund". Për shembull, çdo gjë që ndodh nga momenti kur përdoruesi klikon një buton në një faqe interneti dhe deri në momentin e kthimit të të dhënave, duke përfshirë të gjithë mikroshërbimet e angazhuara në këtë proces. Mund të themi se një gjurmë përshkruan plotësisht (ose modelon) kalimin e kërkesës përpara dhe prapa. Në ndërfaqen Jaeger, gjurmët shfaqen të organizuara në përbërës në boshtin temporal, ashtu si një zinxhir mund të shpërndahen në lidhjet e tij të veçanta. Vetëm që në vend të lidhjeve, gjurma përbëhet nga të ashtuquajturat span.
Span – është intervali nga fillimi i realizimit të një njësie pune deri në përfundimin e saj. Duke vazhduar analogjinë, mund të themi se çdo span përfaqëson një lidhje të veçantë në zinxhir. Span mund të ketë (ose jo) një ose më shumë span të fëmijëve. Si pasojë, span-i më i lartë (root span) do të ketë të njëjtën përmbledhje kohore si gjurma që i referohet.
Monitorimi – është, në të vërtetë, vetë vëzhgimi i sistemit tuaj – me sytë, përmes UI ose mjeteve të automatizimit. Monitorimi bazohet në të dhënat e gjurmimit. Në Istio, monitorimi realizohet me ndihmën e Prometheus dhe ka UI përkatës. Prometheus mbështet monitorimin automatike duke përdorur njoftime Alerts dhe Alert Managers.
Lëmë shenjat
Që gjurmimi të bëhet i mundur, aplikacioni duhet të krijojë një koleksion span. Pastaj ato duhet të eksportohen në Jaeger, në mënyrë që ai të krijojë një paraqitje vizuale të gjurmimit. Ndër të tjera, këto span shënojnë emrin e operacionit, si dhe shenjat e kohës së nisjes dhe përfundimit të tij. Transferimi i span bëhet duke ridrejtuar titujt e HTTP kërkesave të destinuara për Jaeger nga kërkesat hyrëse në ato dalëse. Në varësi të gjuhës së programimit të përdorur, për këtë mund të kërkohet një modifikim i vogël i kodit burimor të aplikacioneve. Më poshtë është një shembull kodi në Java (duke përdorur framework-un Spring Boot), i cili shton titujt B3 (Zipkin-style) në kërkesën tuaj në klasën konfiguruese të Spring:

Këtu përdoren cilësimet e mëposhtme të titujve:

Nëse po përdorni Java, atëherë kodi mund të mos prekët, vetëm shtoni disa rreshta në skedarin POM të Maven dhe caktoni variablat e ambientit. Ja cilat rreshta duhet të shtoni në skedarin POM.XML për të vendosur Jaeger Tracer Resolver:

Dhe variablat përkatës të ambientit caktohen në Dockerfile:

Tani, gjithçka është e konfiguruar, dhe mikroshërbimet tona do të fillojnë të japin të dhëna gjurmimi.
Shikojmë nga një këndvështrim i përgjithshëm
Istio përmban një panel të thjeshtë kontrolli të bazuar në Grafana. Kur gjithçka është e konfiguruar dhe punon mbi platformën Red Hat OpenShift PaaS (në shembullin tonë, Red Hat OpenShift dhe Kubernetes janë vendosur në minishift), ky panel aktivizohet me komandën e mëposhtme:
open "$(minishift openshift service grafana -u)/d/1/istio-dashboard?refresh=5⩝Id=1"
Paneli Grafana lejon një vlerësim të shpejtë të funksionimit të sistemit. Një fragment i këtij paneli është treguar në figurën më poshtë:

Këtu shihet se mikrosërvici customer thërret mikrosërvicin preference v1, i cili nga ana e tij thërret mikrosërvicet recommendation v1 dhe v2. Në panelin Grafana, ka një bllok Dashboard Row për metrikat e nivelit të lartë, siç janë numri i përgjithshëm i kërkesave (Global Request Volume), përqindja e kërkesave të suksesshme (success rates), dhe gabimet 4xx. Përveç kësaj, aty ka një paraqitje të Server Mesh me grafikë për çdo shërbim dhe një bllok Services Row për shikimin e detajeve të plota për çdo kontejner për secilin shërbim.
Tani le të thellohemi më thellë
Me një gjurmim të konfiguruar siç duhet të Istio, i cili, siç quhet, vjen direkt nga kutia, lejon të thellohemi në analizën e performancës së sistemit. Në UI-në e Jaeger-it, mund të shikoni gjurmimet dhe të shihni se sa larg dhe thellë shkojnë ato, si dhe të lokalizoni vizualisht ngushticat në performancë. Kur përdorni Red Hat OpenShift në platformën minishift, nisja e UI-së së Jaeger bëhet me komandën në vijim:
minishift openshift service jaeger-query --in-browser

Çfarë mund të thuhet për gjurmimin në këtë screenshot:
- Ajo ndahen në 7 span-e.
- Koha totale e ekzekutimit është 6.99 ms.
- Për mikrosërvicin recommendation, që është i fundit në zinxhir, shpenzohet 0.69 ms.
Grafikët e këtij lloji ndihmojnë për të kuptuar shpejt situatën kur një shërbim i panjohur po dëmton performancën e gjithë sistemit.
Tani le t’i bëjmë gjërat më komplekse dhe të nisemi me dy ekzemplarë të mikrosërvicit recommendation:v2 me komandën oc scale —replicas=2 deployment/recommendation-v2. Këto janë pod-ët që do të kemi pas kësaj:

Nëse tani kalojmë përsëri në Jaeger dhe hapim span-in për shërbimin recommendation, do të shohim se në cilin pod po drejtohen kërkesat. Kështu, mund të lokalizojmë lehtësisht ngadalësimet në nivelin e një pod-i konkret. Duhet të shikoni në fushën node_id:

Ku dhe si shkon gjithçka
Tani kalojmë në ndërfaqen e Prometheus dhe, siç pritej, shohim atje se kërkesat mes versionit të dytë dhe të parë të shërbimit recommendation ndahen në një raport 2:1, saktësisht sipas numrit të pod-ëve aktivë. Kjo grafik do të ndryshojë dinamikisht gjatë shikimeve të pod-ëve lart-poshtë, gjë që do të jetë veçanërisht e dobishme gjatë Canary Deployment (do t’i trajtojmë këtë skemë të shpërndarjes më në hollësi herën tjetër).

Gjithçka sapo ka filluar
Në të vërtetë sot, siç thuhet, ne thjesht e kemi prekur lehtësisht thesarin e informacionit të dobishëm rreth Jaeger, Grafana dhe Prometheus. Në thelb, kjo ishte edhe qëllimi ynë – t’ju drejtojmë në drejtimin e duhur dhe t’ju hapim perspektivat e Istio.
Dhe mbani mend, të gjitha këto janë tashmë të ndërtuara në Istio. Kur përdorni disa gjuhë programimi (p.sh. Java) dhe framework-e (p.sh. Spring Boot), të gjitha këto mund të realizohen, pa prekur vetë kodin e aplikacioneve. Po, kodi do të duhet të modifikohet paksa nëse përdorni gjuhë të tjera, sidomos Nodejs ose C#. Por pasi gjurmimi (lexo, "trace") është një nga kushtet e domosdoshme për krijimin e sistemeve të besueshme në cloud, do t’ju duhet në çdo rast të rregulloni kodin, pavarësisht nëse keni Istio apo jo. Prandaj, pse të mos e shfrytëzoni këtë përpjekje në një mënyrë më të dobishme?
Të paktën për të qenë gjithmonë në gjendje të përgjigjeni në pyetjet "ku?" dhe "sa shpejt?" me 100% saktësi.
Inxhinieria e kaosit në Istio: kështu është menduar
Aftësia për të prishur gjëra ndihmon për t'i bërë ato të mos prishen
Testimi i softuerit është një gjë jo vetëm komplekse, por edhe e rëndësishme. Në të njëjtën kohë, testimi i saktësisë (p.sh. a kthen funksioni rezultatin e saktë) është një çështje, ndërsa testimi në kushte rrjeti të paqëndrueshëm është një detyrë krejt tjetër (shpesh supozohet se rrjeti gjithmonë punon pa ndërprerje, dhe kjo është e para nga tetë iluzionet mbi llogaritjet e shpërndara). Një nga vështirësitë në zgjidhjen e kësaj çështjeje është se si të simulosh dështimet në sistem ose t'i futësh ato me qëllim, duke kryer atë që quhet injeksion të defekteve. Kjo mund të bëhet përmes modifikimit të kodit burimor të aplikacionit. Por pastaj do të jeni duke testuar jo kodin tuaj origjinal, por një version të tij, i cili simulon posaçërisht defektet. Si rezultat, ju rrezikoni të kapeni në përqafimin vdekjeprurës të injeksionit të defekteve dhe të përballeni me gjezhenbaga – defekte, të cilat zhduken kur përpiqeni t'i zbuloçni.
Tani ne do të tregojmë se si Istio ndihmon të përballojmë këto vështirësi me lehtësi.
Si duket gjithçka kur gjithçka shkon mrekullisht
Le të shqyrtojmë skenarin e mëposhtëm: kemi dy pod-e për mikrosërvicin tonë recommendation, të cilin e kemi marrë nga udhëzuesi i Istio. Një pod është i shënuar si v1, dhe tjetri si v2. Siç e shohim, derisa gjithçka funksionon shkëlqyeshëm:

(P.S. numri në të djathtë është thjesht një numërues thirrjesh për çdo pod)
Por ne nuk kemi nevojë për këtë, a jo? Mirë, le të përpiqemi të prishim gjithçka, pa prekur fare kodin origjinal.
Organizojmë ndërprerje në funksionimin e mikrosërvicit
Më poshtë është një skedar yaml për rregullin e nisjes Istio, i cili do të dështojë (me gabim) në gjysmën e rasteve. server 503):

Vini re, ne qartë e definojmë se në gjysmën e rasteve duhet të kthehet gabimi 503.
Këtu është si do të duket një screenshot i komandës curl, e cila ekzekutohet në cikël pas aktivizimit të këtij rregulli për të imituar dështimet. Siç shohim, gjysma e kërkesave kthejnë gabimin 503, pavarësisht se në cilin pod – v1 ose v2 – ato shkojnë:

Për të rikthyer funksionimin normal, mjafton të fshihet ky rregull, në rastin tonë me komandën istioctl delete routerule recommendation-503 -n tutorial. Këtu Tutorial është emri i projektit Red Hat OpenShift, ku po zhvillohet tutoriali ynë për Istio.
Shtojmë vonesa artificiale
Gabimet artificiale 503 ndihmojnë në testimin e sistemit për qëndrueshmëri ndaj dështimeve, por aftësia për të parashikuar dhe trajtuar vonesat duhet t'ju impresionojë edhe më shumë. Dështimet nuk ndodhin aq shpesh sa vonesat në jetën reale. Një mikrosistem që punon ngadalë është një bllokim që dëmton tërë sistemin. Falë Istio, mund të testoni kodin në lidhje me trajtimin e vonesave pa e ndryshuar atë. Në fillim, ne do të tregojmë se si ta bëjmë këtë në rastin e vonesave që është injektuar në mënyrë artificiale në rrjet.
Vini re, se pas një testi të tillë, ju ndoshta do të keni nevojë (ose do të dëshironit) të përmirësoni kodin tuaj. Lajmi i mirë këtu është se do të veproni proaktivisht, jo reaktivisht. Ky është cikli i zhvillimit që duhet ndjekur: kodim-testim-reagim-kodim-testim...
Këtu është si duket rregulli, që... Çfarë? Istio është kaq e thjeshtë, dhe ky skedar yaml është kaq i qartë, sa gjithçka në këtë shembull flet për vete, vetëm shikoni:

Në gjysmën e rasteve do të kemi një vonesë 7-sekondëshe. Dhe kjo nuk është e njëjtë si nëse do të ishim futur në kodin burimor komandën sleep, sepse Istio realisht e ndalon kërkesën për 7 sekonda. Duke qenë se Istio mbështet trajtimin e Jaeger, kjo vonesë mund të vërehet qartë në UI-në Jaeger, siç tregohet në screenshotin më poshtë. Vini re kërkesën e gjatë në qoshen e sipërme të djathtë të grafikës - koha e saj e përfundimit është 7.02 sekonda:

Ky skenar lejon testimin e kodit nën kushte vonesash rrjetërore. Dhe është evidente se, duke hequr këtë rregull, do të heqim edhe vonesën artificiale. E përsërisim, por ne sërish e bëmë këtë, pa e prekur kodin burimor.
Mos u dorëzoni dhe mos u bëni pasivë
Një tjetër funksion i dobishëm për inxhinierinë e kaosit në Istio është ripërsëritja e kërkesave ndaj shërbimit për një numër të caktuar herësh. Sensi këtu është që të mos ndaloni përpjekjet, kur kërkesa e parë përfundon me një gabim 503 – dhe pastaj, ndoshta, në N-një herë do të kemi fat. Ndoshta, shërbimi thjesht është krijuar për ndonjë arsye për një periudhë të caktuar. Po, kjo arsye duhet të identifikohet dhe të eliminohet. Por kjo është për më vonë, dhe për momentin le të provojmë të bëjmë që sistemi të vazhdojë të punojë.
Pra, ne duam që shërbimi herë pas here të kthejë gabimin 503, dhe Istio pas kësaj të ripërsërisë përpjekjet për ta kontaktuar. Dhe këtu pa dyshim na nevojitet një mënyrë për të gjeneruar gabimin 503 pa e prekur vetë kodin...
Prit, ndalo! Ne sapo e bëmë këtë.
Ky skedar do të bëjë që shërbimi recommendation-v2 në gjysmën e rasteve të kthejë gabimin 503:

E qartë është se disa nga kërkesat do të përfundojnë me dështim:

Tani aktivizojmë funksionin Istio të Ripërsëritjes:

Ky rregull i nisjes bën tre përsëritje me një interval prej dy sekondash dhe duhet të reduktojë (idealisht të eliminojë plotësisht) gabimet 503:

Në përfundim: ne e bëmë që Istio, së pari, të gjenerojë gabimin 503 për gjysmën e kërkesave. Dhe, së dyti, të njëjtën Istio kryen tre përpjekje për të lidhur sërish me shërbimin në rast të gabimit 503. Si rezultat, gjithçka funksionon thjesht shkëlqyeshëm. Pra, duke përdorur funksionin e Ripërsëritjes, ne sostuam premtimin tonë për të mos u dorëzuar.
Dhe po, sërish e bëmë këtë pa e prekur fare kodin. E gjithë çfarë na nevojitet ishin dy rregulla nisjeje Istio:

Si të mos zhgënjejmë përdoruesin ose se shtatë një nuk presin
Tani le ta kthejmë situatën përmbys dhe të shqyrtojmë skenarin kur të mos dorëzohesh dhe të mos heqësh dorë do të thotë vetëm për një periudhë të caktuar. Më pas, duhet të ndalojmë përpjekjet për të trajtuar kërkesën, në mënyrë që të mos e shtyjmë të gjithë të presin për ndonjë shërbim ngadalë që ndalon. Në terma të tjera, ne nuk do të mbrojmë pozita të humbura, por do të tërhiqemi në një pozicion rezervë, për të mos e zhgënjyer përdoruesin e sitit dhe për ta liruar atë nga keqkuptimet.
Në Istio, mund të caktoni kohëzgjatjen e ekzekutimit të kërkesës. Nëse shërbimi tejkalon këtë kohëzgjatje, kthehet një gabim 504 (Gateway Timeout) – kjo gjithashtu bëhet përmes konfigurimit të Istio. Por do të na nevojitet të shtojmë në kodin burimor të shërbimit një komandë sleep (dhe më pas, sigurisht, të kryejmë rebuild dhe redeploy), për të imituar një punë të ngadaltë të shërbimit. Fatkeqësisht, ndryshe nuk do të jetë e mundur.
Pra, ne vendosëm një sleep prej tre sekondash në kodin e shërbimit recommendation v2, rindërtuam imazhin përkatës dhe bëmë redeploy të kontejnerit, tani do të shtojmë një kohëzgjatje përmes këtij rregulli të rrugës Istio:

Në skenarin e mësipërm, shihet se ne ndalojmë përpjekjet për t'u lidhur me shërbimin recommendation, nëse nuk marrim një përgjigje brenda një sekonde, pra akoma përpara se të ndodhte gabimi 504. Pas aplikimit të këtij rregulli të rrugës (dhe shtimit të sleep-it prej tre sekondash në kodin e shërbimit recommendation:v2), do të marrim këtë rezultat:

Përsëri po përsërisim, por kohëzgjatja mund të caktohet pa prekur fare kodin burimor. Një bonus shtesë këtu është se tani mund të modifikoni kodin tuaj në mënyrë që të reagoni ndaj kohëzgjatjes, dhe lehtësisht të testoni këto përmirësime përmes Istio.
Tani gjithçka së bashku
Të sjellësh pak kaos përmes Istio është një mënyrë e shkëlqyer për të testuar kodin tuaj dhe besueshmërinë e sistemit tuaj në përgjithësi. Mënyrat fallback, bulkhead dhe circuit breaker, mekanizmat për të krijuar dështime artificiale dhe vonesa, si dhe thirrjet e përsëritura dhe kohëzgjatjet do të vijnë shumë në ndihmë për krijimin e sistemeve të qëndrueshme në cloud. Së bashku me Kubernetes dhe Red Hat OpenShift, këto mjete do t'ju ndihmojnë të përballoni me besim të ardhmen.
Burimi: habr.com
