Service Tracing, OpenTracing in Jaeger

Service Tracing, OpenTracing in Jaeger

V naših projektih uporabljamo mikrostoritveno arhitekturo. Ko pride do ozkih grl v delovanju, se porabi veliko časa za spremljanje in razčlenjevanje dnevnikov. Pri beleženju časov posameznih operacij v dnevniško datoteko je običajno težko razumeti, kaj je privedlo do priklica teh operacij, slediti zaporedju dejanj ali časovnemu premiku ene operacije glede na drugo v različnih storitvah.

Da bi zmanjšali ročno delo, smo se odločili uporabiti eno od orodij za sledenje. O tem, kako in zakaj lahko uporabite sledenje in kako smo to storili, bomo razpravljali v tem članku.

Katere težave je mogoče rešiti s sledenjem

  1. Poiščite ozka grla v zmogljivosti znotraj posamezne storitve in v celotnem izvajalnem drevesu med vsemi sodelujočimi storitvami. Na primer:
    • Veliko kratkih zaporednih klicev med storitvami, na primer do geokodiranja ali baze podatkov.
    • Dolga V/I čakanja, kot so omrežni prenosi ali branje diska.
    • Dolgo razčlenjevanje podatkov.
    • Dolge operacije, ki zahtevajo procesor.
    • Deli kode, ki niso potrebni za pridobitev končnega rezultata in jih je mogoče odstraniti ali odložiti.
  2. Jasno razumeti, v kakšnem zaporedju se imenuje in kaj se zgodi, ko se operacija izvede.
    Service Tracing, OpenTracing in Jaeger
    Vidi se, da je na primer Zahteva prišla na storitev WS -> storitev WS je dopolnila podatke preko storitve R -> nato poslala zahtevo na storitev V -> storitev V je naložila veliko podatkov iz Storitev R -> šla na storitev P -> storitev P je šla ponovno na storitev R -> storitev V je prezrla rezultat in šla na storitev J -> in šele nato vrnila odgovor storitvi WS, medtem ko je v nadaljevanju računala nekaj drugega ozadje.
    Brez takšne sledi ali podrobne dokumentacije za celoten proces je zelo težko razumeti, kaj se dogaja, ko prvič pogledate kodo, koda pa je razpršena po različnih storitvah in skrita za kopico zabojnikov in vmesnikov.
  3. Zbiranje informacij o izvajalnem drevesu za kasnejšo odloženo analizo. Na vsaki stopnji izvajanja lahko dodate informacije v sled, ki je na voljo na tej stopnji, in nato ugotovite, kateri vhodni podatki so vodili do podobnega scenarija. Na primer:
    • Uporabniško ime
    • pravice
    • Vrsta izbrane metode
    • Napaka v dnevniku ali izvajanju
  4. Spreminjanje sledi v podmnožico metrik in nadaljnja analiza že v obliki metrik.

Kakšna sled se lahko prijavi. Razpon

Pri sledenju obstaja koncept razpona, to je analog enega hloda do konzole. Spa ima:

  • Ime, običajno ime metode, ki je bila izvedena
  • Ime storitve, v kateri je bil razpon ustvarjen
  • Lasten edinstven ID
  • Nekakšna meta informacija v obliki ključa/vrednosti, ki je bila prijavljena vanj. Na primer, parametri metode ali metoda, ki se je končala z napako ali ne
  • Začetni in končni čas za ta razpon
  • ID nadrejenega razpona

Vsak razpon se pošlje zbiralniku razpona, da se shrani v zbirko podatkov za poznejši pregled, takoj ko se zaključi z izvajanjem. V prihodnosti lahko zgradite drevo vseh razponov s povezovanjem po nadrejenem ID-ju. Pri analizi lahko najdete na primer vse razpone v kakšnem servisu, ki je trajal več kot nekaj časa. Nadalje, če greste na določen razpon, si oglejte celotno drevo nad in pod tem razponom.

Service Tracing, OpenTracing in Jaeger

Opentrace, Jagger in kako smo to implementirali za naše projekte

Obstaja skupen standard opentrace, ki opisuje, kako in kaj je treba zbirati, ne da bi bil vezan na določeno izvedbo v katerem koli jeziku. Na primer, v Javi vse delo s sledmi poteka prek skupnega API-ja Opentrace, pod njim pa se lahko skrije na primer Jaeger ali prazna privzeta implementacija, ki ne naredi ničesar.
Uporabljamo Jaeger kot implementacija Opentrace. Sestavljen je iz več komponent:

Service Tracing, OpenTracing in Jaeger

  • Jaeger-agent je lokalni agent, ki je običajno nameščen na vsakem stroju in storitve so vanj prijavljene na lokalnih privzetih vratih. Če agenta ni, so sledi vseh storitev na tem računalniku običajno onemogočene
  • Jaeger-collector - vsi agenti mu pošljejo zbrane sledi, on pa jih postavi v izbrano bazo podatkov
  • Baza podatkov je njihova najprimernejša cassandra, vendar uporabljamo elasticsearch, obstajajo izvedbe za nekaj drugih zbirk podatkov in implementacija v pomnilniku, ki ne shrani ničesar na disk
  • Jaeger-query je storitev, ki gre v bazo podatkov in vrne že zbrane sledi v analizo
  • Jaeger-ui je spletni vmesnik za iskanje in pregledovanje sledi, gre za jaeger-query

Service Tracing, OpenTracing in Jaeger

Ločeno komponento lahko imenujemo implementacija opentrace jaeger za določene jezike, prek katere se razponi pošiljajo jaeger-agentu.
Povezovanje Jaggerja v Javi se zmanjša na implementacijo vmesnika io.opentracing.Tracer, po katerem bodo vse sledi prek njega letele do pravega agenta.

Service Tracing, OpenTracing in Jaeger

Tudi za vzmetno komponento lahko povežete opentracing-spring-cloud-starter in izvajanje Jaegerja opentracing-spring-jaeger-cloud-starter ki bo samodejno konfiguriral sledenje za vse, kar gre skozi te komponente, na primer zahteve http do krmilnikov, zahteve do baze podatkov prek jdbc itd.

Beleženje sledi v Javi

Nekje na najvišjem nivoju je treba ustvariti prvi Span, to lahko naredi avtomatsko, na primer krmilnik vzmeti, ko prejme zahtevo, ali ročno, če je ni. Nato se prenese prek spodnjega obsega. Če katera koli spodnja metoda želi dodati Span, vzame trenutni activeSpan iz obsega, ustvari nov Span in pove, da je njegov nadrejeni nastali activeSpan, ter naredi novi Span aktiven. Pri klicu zunanjih storitev se trenutni aktivni razpon posreduje njim in te storitve ustvarijo nove razpone glede na ta razpon.
Vse delo poteka prek primerka Tracer, lahko ga dobite prek mehanizma DI ali GlobalTracer.get () kot globalne spremenljivke, če mehanizem DI ne deluje. Če sledilnik ni bil inicializiran, bo privzeto vrnil NoopTracer, ki ne naredi ničesar.
Nadalje se trenutni obseg pridobi iz sledilnika prek ScopeManagerja, iz trenutnega se ustvari nov obseg z vezavo novega obsega, nato pa se ustvarjeni obseg zapre, kar zapre ustvarjeni obseg in vrne prejšnji obseg v aktivno stanje. Obseg je vezan na nit, zato pri večnitnem programiranju ne smete pozabiti prenesti aktivnega razpona v drugo nit, za nadaljnjo aktivacijo obsega druge niti glede na ta razpon.

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)) {
        // Do things.
    } 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(() -> {
            // STEP 2 ABOVE: reactivate the Span in the callback, passing true to
            // startActive() if/when the Span must be finished.
            try (Scope scope = tracer.scopeManager().activate(span, false)) {
                ...
            }
        });
    }
}

Za večnitno programiranje obstaja tudi TracedExecutorService in podobni ovoji, ki samodejno posredujejo trenutni razpon v nit, ko se zaženejo asinhrona opravila:

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

Za zunanje http zahteve obstaja TracingHttpClient

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

Težave, s katerimi smo se soočali

  • Beans in DI ne delujeta vedno, če se sledilnik ne uporablja v storitvi ali komponenti Samodejno ožičeno Tracer morda ne bo deloval in boste morali uporabiti GlobalTracer.get().
  • Opombe ne delujejo, če ne gre za komponento ali storitev ali če je metoda poklicana iz sosednje metode istega razreda. Paziti morate, da preverite, kaj deluje, in uporabite ročno ustvarjanje sledi, če @Traced ne deluje. Priložite lahko tudi dodaten prevajalnik za javanske opombe, potem bi morale delovati povsod.
  • V starem pomladnem in pomladnem zagonu samodejna konfiguracija pomladnega oblaka opentraing ne deluje zaradi napak v DI, potem pa, če želite, da sledi v pomladnih komponentah delujejo samodejno, lahko to storite po analogiji z 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
  • Poskusi z viri ne deluje v groovyju, uporabiti moraš poskusi končno.
  • Vsaka storitev mora imeti lastno spring.application.name, pod katerim se bodo beležile sledi. Kaj pomeni ločeno ime za prodajo in test, da ju ne motimo skupaj.
  • Če uporabljate GlobalTracer in tomcat, imajo vse storitve, ki se izvajajo v tem tomcatu, en GlobalTracer, tako da bodo vse imele isto ime storitve.
  • Ko metodi dodajate sledi, morate biti prepričani, da ni večkrat klicana v zanki. Za vse klice je treba dodati eno skupno sled, ki zagotavlja skupni čas dela. V nasprotnem primeru bo nastala presežna obremenitev.
  • Enkrat v jaeger-ui so bile podane prevelike zahteve za veliko število sledi in ker niso čakali na odgovor, so to storili znova. Posledično je jaeger-query začel jesti veliko pomnilnika in upočasnjevati elastičnost. Pomagal s ponovnim zagonom jaeger-query

Vzorčenje, shranjevanje in ogled sledi

Obstajajo tri vrste vzorčenje sledi:

  1. Const, ki pošlje in shrani vse sledi.
  2. Probabilistična, ki filtrira sledi z neko dano verjetnostjo.
  3. Ratelimiting, ki omejuje število sledi na sekundo. Te nastavitve lahko konfigurirate na odjemalcu, bodisi na jaeger-agentu bodisi na zbiralniku. Zdaj uporabljamo const 1 v skladu vrednotenja, ker ni veliko zahtev, vendar trajajo dolgo. V prihodnosti, če bo to prekomerno obremenilo sistem, ga lahko omejite.

Če uporabljate cassandro, privzeto shranjuje sledi le dva dni. Uporabljamo elastično iskanje in sledi so shranjene za ves čas in se ne izbrišejo. Za vsak dan se ustvari ločen indeks, na primer jaeger-service-2019-03-04. V prihodnosti morate konfigurirati samodejno čiščenje starih sledi.

Za ogled sledi potrebujete:

  • Izberite storitev, po kateri želite filtrirati sledi, na primer tomcat7-default za storitev, ki se izvaja v tomcatu in ne more imeti svojega imena.
  • Nato izberite operacijo, časovni interval in minimalni čas operacije, na primer od 10 sekund, da se izvajajo samo dolge izvedbe.
    Service Tracing, OpenTracing in Jaeger
  • Pojdite na eno od sledi in poglejte, kaj se tam upočasnjuje.
    Service Tracing, OpenTracing in Jaeger

Poleg tega, če je nek ID zahteve znan, lahko poiščete sled s tem ID-jem prek iskanja po oznaki, če je ta ID prijavljen v razponu sledenja.

Dokumentacija

Članki

video

Vir: www.habr.com

Dodaj komentar