Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

Në projektet tona përdorim arkitekturën mikroshërbimore. Kur hasim ngushtësi në performancë, shpesh shpenzohet shumë kohë në monitorim dhe analizë të logeve. Duke regjistruar kohën e operacioneve të veçanta në skedarin e logut, zakonisht është e vështirë të kuptohet çfarë çoi në thirrjen e këtyre operacioneve, të ndjekësh renditjen e veprimeve ose të identifikosh devijimin në kohë 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 përcaktimit. Ky artikull do të flasë për se si dhe për çfarë mund të përdoret përcaktimi dhe si e kemi realizuar ne.

ÇfarĂ« probleme mund tĂ« zgjidhen me anĂ« tĂ« pĂ«rcaktimit

  1. Të gjejmë ngushtësitë në performancë si brenda një shërbimi, ashtu edhe në të gjithë pemën e ekzekutimit mes të gjithë shërbimeve të përfshira. Për shembull:
    • ShumĂ« thirrje tĂ« shkurtra njĂ«ra pas tjetĂ«r mes shĂ«rbimeve, pĂ«r shembull, pĂ«r gjeokodimin ose pĂ«r bazĂ«n e tĂ« dhĂ«nave.
    • Pritje tĂ« gjata tĂ« hyrjes dhe daljes, pĂ«r shembull, transferimi i tĂ« dhĂ«nave nĂ« rrjet ose leximi nga disku.
    • AnalizĂ« e gjatĂ« e tĂ« dhĂ«nave.
    • Operacionet e gjata qĂ« kĂ«rkojnĂ« CPU.
    • PjesĂ« kodi qĂ« nuk janĂ« tĂ« nevojshme pĂ«r tĂ« marrĂ« rezultatin pĂ«rfundimtar dhe mund tĂ« hiqen, ose tĂ« ekzekutohen me vonesĂ«.
  2. Të kuptohet qartë se në cilin rend ndodhin thirrjet dhe çfarë ndodh kur ekzekutohet një operacion.
    Përcaktimi i shërbimeve, OpenTracing dhe Jaeger
    ËshtĂ« e dukshme se, pĂ«r shembull, KĂ«rkesa erdhi nĂ« shĂ«rbimin WS -> shĂ«rbimi WS e plotĂ«soi informacionin pĂ«rmes shĂ«rbimit R -> mĂ« pas dĂ«rgoi kĂ«rkesĂ«n 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Ă«rbimin R -> shĂ«rbimi V e injoroi rezultatin dhe shkoi nĂ« shĂ«rbimin J -> dhe vetĂ«m atĂ«herĂ« ktheu pĂ«rgjigjen nĂ« shĂ«rbimin WS, duke vazhduar nĂ« sfond tĂ« llogariste diçka tjetĂ«r.
    Pa një gjurmimi të tillë ose dokumentim të detajuar për të gjithë procesin, është shumë e vështirë të kuptohet se çfarë ndodh duke e parë për herë të parë kodin, dhe kodet shpesh janë të shpërndara në shërbime të ndryshme dhe të fshehura pas shumë bin-ve dhe ndërfaqeve.
  3. Grumbullimi i informacionit në lidhje me pemën e ekzekutimit për analizë të ardhshme të vonuar. Në çdo fazë të ekzekutimit, mund të shtohet informacion në gjurmë i cili është i disponueshëm në atë fazë dhe më pas të analizojmë se cilat të dhëna hyrëse çuan në një skenar të tillë. Për shembull:
    • ID e pĂ«rdoruesit
    • TĂ« drejtat
    • Lloji i metodĂ«s sĂ« zgjedhur
    • Logu ose gabim ekzekutimi
  4. Shndërrimi i gjurmëve në një nënshtresë metrikash dhe analiza e mëtejshme tashmë në formën e metrikeve.

ÇfarĂ« mund tĂ« regjistrojĂ« gjurmimi. Span

Në gjurmim ka një koncept të span-it, i cili është ekuivalenti i një logu në konsolë. Një span ka:

  • Emrin, zakonisht emri i metodĂ«s qĂ« Ă«shtĂ« ekzekutuar
  • Emri i shĂ«rbimit nĂ« tĂ« cilin Ă«shtĂ« gjeneruar span-i
  • ID-ja unike e tij
  • NjĂ« lloj informacioni meta nĂ« formĂ«n e çelĂ«sit/p value, tĂ« cilin e kanĂ« regjistruar nĂ« tĂ«. P.sh., parametrat e metodĂ«s ose nĂ«se metoda pĂ«rfundoi me njĂ« gabim apo jo
  • Koha e fillimit dhe pĂ«rfundimit tĂ« ekzekutimit tĂ« kĂ«tij span-i
  • ID e span-it prind

Çdo span dĂ«rgohet nĂ« kolektorin e span-ave pĂ«r ruajtje nĂ« bazĂ«n e tĂ« dhĂ«nave pĂ«r shikim tĂ« mĂ«vonshĂ«m sapo tĂ« pĂ«rfundojĂ« ekzekutimi i tij. MĂ« pas, mund tĂ« ndĂ«rtohet njĂ« pemĂ« e tĂ« gjitha span-ave duke lidhur sipas ID-sĂ« prind. GjatĂ« analizĂ«s, mund tĂ« gjeni, pĂ«r shembull, tĂ« gjitha span-at nĂ« njĂ« shĂ«rbim tĂ« caktuar qĂ« kanĂ« marrĂ« mĂ« shumĂ« se njĂ« kohĂ« tĂ« caktuar. Pastaj, duke kaluar nĂ« njĂ« span tĂ« caktuar, tĂ« shihni tĂ« gjithĂ« pemĂ«n lart dhe poshtĂ« kĂ«tij span-i.

Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

Opentrace, Jaeger dhe si e kemi realizuar këtë për projektet tona

Ekziston një standard i përgjithshëm Opentrace, i cili përshkruan se si dhe çfarë duhet të mbledhë, pa lidhur gjurmimin me një implementim të caktuar në një gjuhë të caktuar. Për shembull, në Java, të gjitha veprimet me gjurmët realizohen përmes një API të përbashkët Opentrace, dhe nën të mund të fshihet, p.sh., Jaeger ose një implementim default bosh që nuk bën asgjë.
Ne përdorim Jaeger si implementim të Opentrace. Ai përbëhet nga disa komponentë:

Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

  • Jaeger-agent — agjenti lokal, i cili zakonisht gjendet nĂ« çdo makinĂ« dhe nĂ« tĂ« regjistrohen shĂ«rbimet nĂ« portin e tij default lokal. NĂ«se agjenti mungon, atĂ«herĂ« gjurmĂ«t e tĂ« gjitha shĂ«rbimeve nĂ« kĂ«tĂ« makinĂ« zakonisht janĂ« tĂ« fikura.
  • Jaeger-collector — tĂ« gjithĂ« agjentĂ«t dĂ«rgojnĂ« gjurmĂ«t e mbledhura nĂ« tĂ«, dhe ai i ruan ato nĂ« bazĂ«n e tĂ« dhĂ«nave tĂ« zgjedhur.
  • Baza e tĂ« dhĂ«nave — e preferuara pĂ«r ta Ă«shtĂ« Cassandra, por ne pĂ«rdorim Elasticsearch, ka implementime edhe pĂ«r disa baza tĂ« tjera tĂ« dhĂ«nash dhe njĂ« implementim nĂ« memorie, i cili nuk ruan asgjĂ« nĂ« disk.
  • Jaeger-query — Ă«shtĂ« njĂ« shĂ«rbim qĂ« shkon nĂ« bazĂ«n e tĂ« dhĂ«nave dhe jep gjurmĂ«t e mbledhura pĂ«r analizĂ«.
  • Jaeger-ui — Ă«shtĂ« ndĂ«rfaqja web pĂ«r kĂ«rkimin dhe shikimin e gjurmĂ«ve, ajo shkon tek jaeger-query.

Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

Një komponent i veçantë mund të quhet implementimi i opentrace jaeger për gjuhë të caktuara, përmes së cilës span-at dërgohen tek jaeger-agent.
Konfigurimi i Jaeger në Java duhet të implementohet ndërfaqja io.opentracing.Tracer, pas së cilës të gjitha gjurmët do të dërgohen përmes saj në agjentin e vërtetë.

Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

Po ashtu për komponentët e Spring mund të lidhni opentracing-spring-cloud-starter dhe implementimin nga Jaeger opentracing-spring-jaeger-cloud-starter e cila do të konfigurojë automatikisht gjurmimin për çdo gjë që kalon përmes këtyre komponentëve, për shembull kërkesat http në kontrollet, kërkesat për databazën përmes jdbc, etj.

Logging i gjurmëve në Java

Diku në nivelin më të lartë duhet të krijohet Span-i i parë, kjo mund të bëhet automatikisht për shembull nga kontrolluesi i Spring kur merr një kërkesë, ose manualisht nëse nuk ka të tillë. Më pas ai kalon përmes Scope-it poshtë. Nëse ndonjë metodë poshtë dëshiron të shtojë një Span, ajo merr nga Scope-i current activeSpan, krijon një Span të ri dhe tregon që parent-i i tij është activeSpan i marrë, dhe e bën Span-in e ri aktiv. Kur thirren shërbime të jashtme, atyre u kalon aktuali active span, dhe ato shërbime krijojnë Spans të reja në lidhje me këtë span.
E gjithë puna bëhet përmes instancës Tracer, mund ta merrni atë përmes mekanizmit DI, ose GlobalTracer.get() si një variabël globale, nëse mekanizmi DI nuk funksionon. Nëse traci nuk është inicializuar, do të kthehet NoopTracer që nuk bën asgjë.
Më pas nga traci përmes ScopeManager merret scope-i aktual, krijohet një scope i ri nga ai aktual me lidhje nga një span i ri, dhe më pas mbyllet Scope-i i krijuar, i cili mbyll span-in e krijuar dhe kthen në gjendje aktive Scope-in e mëparshëm. Scope-i është i lidhur me thread-in, prandaj gjatë programimit me shumë threads nuk duhet të harrohet të kaloni active span-in në thread tjetër, për aktivizimin më të tutjeshëm të Scope-it të thread-it tjetër me lidhje me këtë span.

io.opentracing.Tracer tracer = ...; // GlobalTracer.get()

void DoSmth () {
   try (Scope scope = tracer.buildSpan("DoSmth").startActive(true)) {
      ...
   }
}
void DoOther () {
    Span span = tracer.buildSpan("someWork").start();
    try (Scope scope = tracer.scopeManager().activate(span, false)) {
        // Bëni gjëra.
    } catch(Exception ex) {
        Tags.ERROR.set(span, true);
        span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, ex, Fields.MESSAGE, ex.getMessage()));
    } finally {
        span.finish();
    }
}

void DoAsync () {
    try (Scope scope = tracer.buildSpan("ServiceHandlerSpan").startActive(false)) {
        ...
        final Span span = scope.span();
        doAsyncWork(() -> {
            // HAPI 2 MË SIPËR: rikthe Span-in nĂ« callback, duke kaluar true nĂ«
            // startActive() nëse/kohë kur duhet përfunduar Span-i.
            try (Scope scope = tracer.scopeManager().activate(span, false)) {
                ...
            }
        });
    }
}

Për programimin me shumë përgjegjësi, ekziston gjithashtu TracedExecutorService dhe mbështetje të ngjashme, të cilat automatikisht përçojnë spanin aktual në thread kur fillojnë detyrat asinkrone:

private ExecutorService executor = new TracedExecutorService(
    Executors.newFixedThreadPool(10), GlobalTracer.get()
);

Për kërkesat http të jashtme, ka TracingHttpClient

HttpClient httpClient = new TracingHttpClientBuilder().build();

Problemet me të cilat u përballëm

  • Bean-Ă«t dhe DI nuk funksionojnĂ« gjithmonĂ« nĂ«se tracer pĂ«rdoret jashtĂ« shĂ«rbimit ose komponentit, nĂ« atĂ« rast Autowired Tracer mund tĂ« mos funksionojĂ« dhe do tĂ« duhet tĂ« pĂ«rdorim GlobalTracer.get().
  • Anotacionet nuk funksionojnĂ« nĂ«se nuk Ă«shtĂ« njĂ« komponent ose shĂ«rbim, ose nĂ«se thirrja e metodĂ«s ndodh nga njĂ« metodĂ« tjetĂ«r e sĂ« njĂ«jtĂ«s klasĂ«. Duhet tĂ« jemi tĂ« kujdesshĂ«m, tĂ« kontrollojmĂ« çfarĂ« funksionon dhe tĂ« pĂ«rdorim krijimin manual tĂ« traces nĂ«se @Traced nuk funksionon. Gjithashtu mund tĂ« lidhim njĂ« kompajler shtesĂ« pĂ«r anotacionet java, atĂ«herĂ« duhet tĂ« funksionojnĂ« nĂ« çdo vend.
  • NĂ« versionet e vjetra tĂ« spring dhe spring boot, konfigurimi automatik i opentracing spring cloud nuk funksionon pĂ«r shkak tĂ« defekteve nĂ« DI, kĂ«shtu qĂ« nĂ«se dĂ«shirojmĂ« qĂ« traces nĂ« komponentet e springut tĂ« funksionojnĂ« automatikisht, mund tĂ« veprojmĂ« si te github.com/opentracing-contrib/java-spring-jaeger/blob/master/opentracing-spring-jaeger-starter/src/main/java/io/opentracing/contrib/java/spring/jaeger/starter/JaegerAutoConfiguration.java
  • NĂ« groovy, nuk funksionon try with resources, duhet tĂ« pĂ«rdorim gjithmonĂ« try finally.
  • Çdo shĂ«rbim duhet tĂ« ketĂ« emrin e vet spring.application.name nĂ«n tĂ« cilin do tĂ« regjistrohen traces. Po ashtu njĂ« emĂ«r tĂ« veçantĂ« pĂ«r prodhimin dhe testin, pĂ«r tĂ« mos e ndĂ«rthurur ato sĂ« bashku.
  • NĂ«se pĂ«rdorim GlobalTracer dhe tomcat, tĂ« gjitha shĂ«rbimet e nisura nĂ« kĂ«tĂ« tomcat kanĂ« njĂ« GlobalTracer, ndaj do tĂ« kenĂ« tĂ« gjithĂ« tĂ« njĂ«jtin emĂ«r shĂ«rbimi.
  • NĂ« momentin qĂ« shtojmĂ« traces nĂ« metodĂ«, duhet tĂ« jemi tĂ« sigurt qĂ« ajo nuk thirret nĂ« njĂ« cikĂ«l shumĂ« herĂ«. Duhet tĂ« shtojmĂ« njĂ« trace tĂ« pĂ«rbashkĂ«t pĂ«r tĂ« gjitha thirrjet, e cila do tĂ« regjistrojĂ« kohĂ«n totale tĂ« punĂ«s. Ndryshe do tĂ« krijohet njĂ« ngarkesĂ« e tepĂ«rt.
  • NjĂ« herĂ« nĂ« jaeger-ui bĂ«mĂ« kĂ«rkesa shumĂ« tĂ« mĂ«dha pĂ«r njĂ« sasi tĂ« madhe traces dhe pasi nuk prisnim pĂ«rgjigjen, bĂ«mĂ« atĂ« pĂ«rsĂ«ri. Si rezultat jaeger-query filloi tĂ« hante shumĂ« memorje dhe ngadalĂ«sonte elastikun. E ndihmoi rinovimi i jaeger-query.

Sampling, ruajtja dhe shikimi i traces

Ekzistojnë tre tipe sampling-u i traces:

  1. Const i cili dërgon dhe ruan të gjitha traces.
  2. Probabilistic i cili filtrin traces me një probabilitet të caktuar.
  3. Ratelimiting që kufizon numrin e trasheve në sekondë. Këto parametra mund të konfigurohen në klient, ose në jaeger-agent ose në kolektor. Tani në stack-un tonë të validuesve përdorim const 1 pasi kërkesat nuk janë shumë, por ato zgjatin një kohë të gjatë. Në të ardhmen, nëse kjo do të shkaktojë një ngarkesë të tepruar në sistem, mund të kufizojmë.

Nëse përdorim Cassandra, atëherë për default ajo ruan trashet vetëm për dy ditë. Ne përdorim elasticsearch dhe trashet ruhen gjithmonë dhe nuk fshihen. Për çdo ditë krijohet një indeks i veçantë, për shembull jaeger-service-2019-03-04. Në të ardhmen duhet të konfigurojmë pastrimin automatik të trasheve të vjetra.

Për të parë trashet, duhet:

  • TĂ« zgjedhim shĂ«rbimin pĂ«r tĂ« cilin dĂ«shirojmĂ« tĂ« filtrojmĂ« trashet, pĂ«r shembull tomcat7-default pĂ«r shĂ«rbimin qĂ« Ă«shtĂ« aktivizuar nĂ« Tomcat dhe nuk mund tĂ« ketĂ« emrin e tij.
  • Pastaj tĂ« zgjedhim operacionin, intervalin kohor dhe kohĂ«n minimale tĂ« operacionit, pĂ«r shembull nga 10 sekonda, pĂ«r tĂ« marrĂ« vetĂ«m ekzekutimet e gjata.
    Përcaktimi i shërbimeve, OpenTracing dhe Jaeger
  • TĂ« kalojmĂ« nĂ« njĂ« nga trashet dhe tĂ« shikojmĂ« çfarĂ« e ngadalĂ«sonte atje.
    Përcaktimi i shërbimeve, OpenTracing dhe Jaeger

Po ashtu, nëse dihet një id e caktuar e kërkesës, atëherë mund të gjejmë trashe të dhënë përmes këtij id nëpërmjet kërkimit sipas etiketeve, nëse ky id logarohet në span e trashe.

Dokumentacioni

Artikuj

Video

Burimi: habr.com

Bleni hostin e besueshĂ«m pĂ«r faqet me mbrojtje nga DDoS, VPS VDS servera đŸ”„ Bli hostin e besueshĂ«m pĂ«r faqet me mbrojtje nga DDoS, VPS VDS servera | ProHoster