Ne përdorim arkitekturën e mikroshërbimeve në projektet tona. Kur ndodhin pengesa në performancë, harxhohet shumë kohë për monitorimin dhe analizimin e regjistrave. Kur regjistroni kohën e operacioneve individuale në një skedar log, zakonisht është e vështirë të kuptohet se çfarë çoi në thirrjen e këtyre operacioneve, për të gjurmuar sekuencën e veprimeve ose zhvendosjen kohore të një operacioni në lidhje me një tjetër në shërbime të ndryshme.
Për të minimizuar punën manuale, vendosëm të përdorim një nga mjetet e gjurmimit. Rreth asaj se si dhe pse mund të përdorni gjurmimin dhe si e bëmë atë, dhe do të diskutohet në këtë artikull.
Cilat probleme mund të zgjidhen me gjurmim
Gjeni pengesat e performancës si brenda një shërbimi të vetëm ashtu edhe në të gjithë pemën e ekzekutimit midis të gjitha shërbimeve pjesëmarrëse. Për shembull:
Shumë thirrje të shkurtra të njëpasnjëshme ndërmjet shërbimeve, për shembull, në gjeokodim ose në një bazë të dhënash.
Pritjet e gjata hyrëse/dalëse, të tilla si transferimet në rrjet ose leximet e diskut.
Analizimi i gjatë i të dhënave.
Operacione të gjata që kërkojnë CPU.
Seksione të kodit që nuk nevojiten për të marrë rezultatin përfundimtar dhe mund të hiqen ose vonohen.
Kuptoni qartë se në çfarë sekuence quhet dhe çfarë ndodh kur kryhet operacioni.
Mund të shihet se, për shembull, Kërkesa erdhi në shërbimin WS -> shërbimi WS plotësoi të dhënat përmes shërbimit R -> më pas dërgoi një kërkesë në shërbimin V -> shërbimi V ngarkoi shumë të dhëna nga Shërbimi R -> shkoi në shërbimin P -> shërbimi P shkoi përsëri në shërbim R -> shërbimi V injoroi rezultatin dhe shkoi në shërbimin J -> dhe vetëm më pas ktheu përgjigjen në shërbimin WS, ndërsa vazhdon të llogarisë diçka tjetër në sfondin.
Pa një gjurmë të tillë apo dokumentacion të detajuar për të gjithë procesin, është shumë e vështirë të kuptosh se çfarë po ndodh kur shikon kodin për herë të parë, dhe kodi shpërndahet nëpër shërbime të ndryshme dhe fshihet pas një grupi koshësh dhe ndërfaqesh.
Mbledhja e informacionit në lidhje me pemën e ekzekutimit për analizën e mëvonshme të shtyrë. Në çdo fazë të ekzekutimit, mund të shtoni informacion në gjurmën që është i disponueshëm në këtë fazë dhe më pas të kuptoni se cilat të dhëna hyrëse çuan në një skenar të ngjashëm. Për shembull:
ID e përdoruesit
Të drejtat
Lloji i metodës së zgjedhur
Gabim i regjistrit ose ekzekutimit
Kthimi i gjurmëve në një nëngrup metrikash dhe analiza e mëtejshme tashmë në formën e metrikës.
Çfarë gjurme mund të regjistrohet. Hapësirë
Në gjurmim ekziston koncepti i një hapësire, ky është një analog i një regjistri, me tastierën. Spa ka:
Emri, zakonisht emri i metodës që u ekzekutua
Emri i shërbimit në të cilin u krijua hapësira
Vetë ID unike
Një lloj meta informacioni në formën e një çelësi/vlere që është regjistruar në të. Për shembull, parametrat e metodës ose metoda përfundoi me një gabim ose jo
Koha e fillimit dhe e përfundimit për këtë periudhë
ID-ja e hapësirës së prindit
Çdo hapësirë i dërgohet kolektorit të hapësirës për t'u ruajtur në bazën e të dhënave për rishikim të mëvonshëm sapo të ketë përfunduar ekzekutimin e tij. Në të ardhmen, mund të ndërtoni një pemë të të gjitha hapësirave duke u lidhur me ID-në e prindit. Kur analizoni, mund të gjeni, për shembull, të gjitha shtrirjet në një shërbim që zgjati më shumë se pak kohë. Më tej, duke shkuar në një hapësirë specifike, shihni të gjithë pemën sipër dhe poshtë kësaj hapësire.
Opentrace, Jagger dhe si e zbatuam atë për projektet tona
Ekziston një standard i përbashkët gjurmë të hapura, i cili përshkruan se si dhe çfarë duhet të mblidhet, pa u lidhur me një zbatim specifik në asnjë gjuhë. Për shembull, në Java, e gjithë puna me gjurmët kryhet përmes API-së së zakonshme Opentrace, dhe nën të, për shembull, Jaeger ose një zbatim i paracaktuar bosh që nuk bën asgjë mund të fshihet.
Ne jemi duke përdorur Jaeger si një zbatim i Opentrace. Ai përbëhet nga disa komponentë:
Jaeger-agent është një agjent lokal që zakonisht instalohet në çdo makinë dhe shërbimet regjistrohen në të në portën e paracaktuar lokale. Nëse nuk ka agjent, atëherë gjurmët e të gjitha shërbimeve në këtë makinë zakonisht çaktivizohen
Jaeger-collector - të gjithë agjentët i dërgojnë gjurmët e mbledhura tek ai dhe ai i vendos ato në bazën e të dhënave të zgjedhur
Baza e të dhënave është cassandra e tyre e preferuar, por ne përdorim elasticsearch, ka zbatime për disa baza të tjera të dhënash dhe një zbatim në memorie që nuk kursen asgjë në disk
Jaeger-query është një shërbim që shkon në bazën e të dhënave dhe kthen gjurmët e mbledhura tashmë për analizë
Jaeger-ui është një ndërfaqe në internet për kërkimin dhe shikimin e gjurmëve, shkon te jaeger-query
Një komponent i veçantë mund të quhet zbatimi i opentrace jaeger për gjuhë të veçanta, përmes të cilit spans dërgohen te jaeger-agent. Lidhja e Jagger në Java zbret në zbatimin e ndërfaqes io.opentracing.Tracer, pas së cilës të gjitha gjurmët përmes saj do të fluturojnë te agjenti real.
Gjithashtu për komponentin e pranverës, mund të lidheni opentracing-pranverë-re-starter dhe zbatimi nga Jaeger opentracing-pranverë-jaeger-cloud-starter i cili automatikisht do të konfigurojë gjurmimin për çdo gjë që kalon përmes këtyre komponentëve, për shembull kërkesat http drejt kontrolluesve, kërkesat për bazën e të dhënave përmes jdbc, etj.
Gjurmët e regjistrimit në Java
Diku në nivelin më të lartë, duhet të krijohet Hapësira e parë, kjo mund të bëhet automatikisht, për shembull, nga kontrolluesi i pranverës kur merret një kërkesë, ose manualisht nëse nuk ka. Më pas transmetohet përmes Fushëveprimit më poshtë. Nëse ndonjë metodë më poshtë dëshiron të shtojë një Hapësirë, ajo merr activeSpan-in aktual nga Scope, krijon një hapësirë të re dhe thotë se prindi i saj është activeSpan-i që rezulton dhe e bën aktiv Hapësirën e re. Kur telefononi shërbime të jashtme, hapësira aktuale aktive u kalon atyre dhe ato shërbime krijojnë hapësira të reja duke iu referuar kësaj hapësirë.
E gjithë puna kalon përmes shembullit Tracer, ju mund ta merrni atë përmes mekanizmit DI, ose GlobalTracer.get () si një ndryshore globale nëse mekanizmi DI nuk funksionon. Si parazgjedhje, nëse gjurmuesi nuk është inicializuar, NoopTracer do të kthehet i cili nuk bën asgjë.
Më tej, shtrirja aktuale merret nga gjurmuesi përmes ScopeManager, krijohet një fushë e re nga ajo aktuale me një lidhje të hapësirës së re, dhe më pas mbyllet Scope e krijuar, e cila mbyll hapësirën e krijuar dhe kthen shtrirjen e mëparshme në gjendjen aktive. Scope është i lidhur me një thread, kështu që kur programoni me shumë fije, nuk duhet të harroni të transferoni hapësirën aktive në një thread tjetër, për aktivizimin e mëtejshëm të Scope të një thread tjetër në lidhje me këtë hapësirë.
Për programimin me shumë fije, ekziston gjithashtu TracedExecutorService dhe mbështjellës të ngjashëm që përcjellin automatikisht hapësirën aktuale në thread kur hapen detyrat asinkrone:
private ExecutorService executor = new TracedExecutorService(
Executors.newFixedThreadPool(10), GlobalTracer.get()
);
HttpClient httpClient = new TracingHttpClientBuilder().build();
Problemet me të cilat u përballëm
Fasulet dhe DI nuk funksionojnë gjithmonë nëse gjurmuesi nuk përdoret në një shërbim ose komponent, atëherë Me kabllo automatike Tracer mund të mos funksionojë dhe do t'ju duhet të përdorni GlobalTracer.get().
Shënimet nuk funksionojnë nëse nuk është një komponent ose shërbim, ose nëse metoda thirret nga një metodë fqinje e së njëjtës klasë. Duhet të jeni të kujdesshëm për të kontrolluar se çfarë funksionon dhe të përdorni krijimin manual të gjurmëve nëse @Traced nuk funksionon. Ju gjithashtu mund të bashkëngjitni një përpilues shtesë për shënimet java, atëherë ato duhet të funksionojnë kudo.
Provoni me burime nuk funksionon në groovy, duhet të përdorni më në fund provoni.
Çdo shërbim duhet të ketë emrin e vet Spring.application.në të cilin do të regjistrohen gjurmët. Çfarë bën një emër të veçantë për shitjen dhe testin, në mënyrë që të mos ndërhyjnë me to së bashku.
Nëse përdorni GlobalTracer dhe tomcat, atëherë të gjitha shërbimet që funksionojnë në këtë tomcat kanë një GlobalTracer, kështu që të gjitha do të kenë të njëjtin emër shërbimi.
Kur shtoni gjurmë në një metodë, duhet të jeni të sigurt që ajo nuk thirret shumë herë në një lak. Është e nevojshme të shtohet një gjurmë e përbashkët për të gjitha thirrjet, e cila garanton kohën totale të punës. Përndryshe, do të krijohet një ngarkesë e tepërt.
Pasi në jaeger-ui, u bënë kërkesa shumë të mëdha për një numër të madh gjurmësh dhe meqenëse nuk prisnin përgjigje, e bënë përsëri. Si rezultat, jaeger-query filloi të hante shumë memorie dhe të ngadalësonte elasticitetin. Ndihmuar duke rifilluar jaeger-query
Probabilistik që filtron gjurmët me një probabilitet të caktuar.
Ratelimiting i cili kufizon numrin e gjurmëve për sekondë. Ju mund t'i konfiguroni këto cilësime në klient, qoftë në agjentin jaeger ose në kolektor. Tani ne përdorim const 1 në raftin e vlerësuesit, pasi nuk ka shumë kërkesa, por ato kërkojnë shumë kohë. Në të ardhmen, nëse kjo do të ushtrojë një ngarkesë të tepërt në sistem, mund ta kufizoni atë.
Nëse përdorni cassandra, atëherë si parazgjedhje ruan gjurmë vetëm për dy ditë. Ne jemi duke përdorur kërkesë elastike dhe gjurmët ruhen gjatë gjithë kohës dhe nuk fshihen. Një indeks i veçantë krijohet për çdo ditë, për shembull jaeger-service-2019-03-04. Në të ardhmen, duhet të konfiguroni pastrimin automatik të gjurmëve të vjetra.
Për të parë gjurmët që ju nevojiten:
Zgjidhni shërbimin me të cilin dëshironi të filtroni gjurmët, për shembull, tomcat7-default për një shërbim që funksionon në tomcat dhe nuk mund të ketë emrin e vet.
Pastaj zgjidhni operacionin, intervalin kohor dhe kohën minimale të funksionimit, për shembull nga 10 sekonda, për të marrë vetëm ekzekutime të gjata.
Shkoni në një nga gjurmët dhe shikoni se çfarë po ngadalësohej atje.
Gjithashtu, nëse dihet ndonjë id kërkese, atëherë mund të gjeni një gjurmë nga kjo id përmes një kërkimi të etiketave, nëse kjo id është regjistruar në hapësirën e gjurmës.