Service Tracing, OpenTracing i Jaeger

Service Tracing, OpenTracing i Jaeger

U našim projektima koristimo mikroservisnu arhitekturu. Kada se pojave uska grla u izvedbi, puno se vremena troši na praćenje i raščlanjivanje dnevnika. Prilikom bilježenja vremena pojedinačnih operacija u datoteku dnevnika, obično je teško razumjeti što je dovelo do pozivanja tih operacija, pratiti slijed radnji ili vremenski pomak jedne operacije u odnosu na drugu u različitim uslugama.

Kako bismo smanjili ručni rad, odlučili smo upotrijebiti jedan od alata za praćenje. O tome kako i zašto možete koristiti praćenje i kako smo to učinili, a bit će riječi u ovom članku.

Koji se problemi mogu riješiti praćenjem

  1. Pronađite uska grla u izvedbi i unutar jedne usluge i u cijelom stablu izvršenja između svih usluga koje sudjeluju. Na primjer:
    • Mnogo kratkih uzastopnih poziva između usluga, na primjer, geokodiranja ili baze podataka.
    • Duga I/O čekanja, kao što su mrežni prijenosi ili čitanja diska.
    • Dugo analiziranje podataka.
    • Duge operacije koje zahtijevaju CPU.
    • Dijelovi koda koji nisu potrebni za dobivanje konačnog rezultata i mogu se ukloniti ili odgoditi.
  2. Jasno razumjeti u kojem slijedu što se zove i što se događa kada se operacija izvodi.
    Service Tracing, OpenTracing i Jaeger
    Vidi se da je npr. Zahtjev došao na WS servis -> WS servis je dopunio podatke preko R servisa -> zatim poslao zahtjev V servisu -> V servis je učitao dosta podataka iz R servis -> otišao na P servis -> P servis je ponovo otišao na servis R -> servis V zanemario rezultat i otišao na servis J -> i tek tada vratio odgovor servisu WS, dok je nastavio računati nešto drugo u pozadina.
    Bez takvog traga ili detaljne dokumentacije za cijeli proces, vrlo je teško razumjeti što se događa kada prvi put pogledate kod, a kod je razbacan po različitim servisima i skriven iza hrpe spremnika i sučelja.
  3. Prikupljanje informacija o stablu izvršenja za naknadnu odgođenu analizu. U svakoj fazi izvođenja možete dodati informacije praćenju koje su dostupne u ovoj fazi i zatim otkriti koji su ulazni podaci doveli do sličnog scenarija. Na primjer:
    • ID korisnika
    • prava
    • Vrsta odabrane metode
    • Pogreška u zapisniku ili izvršenju
  4. Pretvaranje tragova u podskup metrike i daljnja analiza već u obliku metrike.

Što trag može log. Raspon

U praćenju postoji koncept raspona, to je analog jednog dnevnika, na konzoli. Spa ima:

  • Naziv, obično naziv metode koja je izvršena
  • Naziv usluge u kojoj je raspon generiran
  • Vlastiti jedinstveni ID
  • Neka vrsta meta informacija u obliku ključa/vrijednosti koji je upisan u njega. Na primjer, parametri metode ili je metoda završila s pogreškom ili ne
  • Vrijeme početka i završetka za ovaj raspon
  • ID nadređenog raspona

Svaki raspon se šalje sakupljaču raspona kako bi se pohranio u bazu podataka za kasniji pregled čim dovrši svoje izvršenje. U budućnosti možete izgraditi stablo svih raspona povezivanjem prema nadređenom ID-u. Prilikom analize možete pronaći npr. sve raspone u nekom servisu koji je trajao više od nekog vremena. Nadalje, odlaskom na određeni raspon, vidite cijelo stablo iznad i ispod ovog raspona.

Service Tracing, OpenTracing i Jaeger

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

Postoji zajednički standard opentrace, koji opisuje kako i što treba prikupljati, bez vezivanja praćenjem za određenu implementaciju na bilo kojem jeziku. Na primjer, u Javi se sav rad s tragovima odvija preko zajedničkog Opentrace API-ja, a ispod njega se može sakriti npr. Jaeger ili prazna zadana implementacija koja ne radi ništa.
Koristimo se Strijelac kao implementacija Opentracea. Sastoji se od nekoliko komponenti:

Service Tracing, OpenTracing i Jaeger

  • Jaeger-agent je lokalni agent koji se obično instalira na svakom računalu i usluge se prijavljuju na njega na lokalnom zadanom priključku. Ako nema agenta, tada su tragovi svih usluga na ovom stroju obično onemogućeni
  • Jaeger-collector - svi agenti mu šalju prikupljene tragove, a on ih stavlja u odabranu bazu podataka
  • Baza podataka je njihova preferirana kasandra, ali mi koristimo elasticsearch, postoje implementacije za nekoliko drugih baza podataka i implementacija u memoriji koja ne sprema ništa na disk
  • Jaeger-query je servis koji odlazi u bazu i vraća već prikupljene tragove na analizu
  • Jaeger-ui je web sučelje za pretraživanje i pregled tragova, ide na jaeger-query

Service Tracing, OpenTracing i Jaeger

Zasebna komponenta može se nazvati implementacija opentrace jaeger-a za određene jezike, preko koje se rasponi šalju jaeger-agentu.
Povezivanje Jaggera u Javi svodi se na implementaciju io.opentracing.Tracer sučelja, nakon čega će svi tragovi kroz njega letjeti do pravog agenta.

Service Tracing, OpenTracing i Jaeger

Također za opružnu komponentu, možete spojiti opentracing-spring-cloud-starter a implementacija od Jaegera opentracing-spring-jaeger-cloud-starter koji će automatski konfigurirati praćenje za sve što prolazi kroz ove komponente, na primjer http zahtjeve prema kontrolerima, zahtjeve prema bazi podataka kroz jdbc itd.

Zapisivanje tragova u Javi

Negdje na najvišoj razini mora se kreirati prvi Span, to se može učiniti automatski, npr. pomoću opružnog kontrolera kada se primi zahtjev ili ručno ako ga nema. Zatim se prenosi kroz Opseg u nastavku. Ako bilo koja od metoda u nastavku želi dodati Span, uzima trenutni activeSpan iz Scopea, stvara novi Span i kaže da je njegov nadređeni rezultirajući activeSpan, te novi Span čini aktivnim. Prilikom pozivanja vanjskih usluga, trenutni aktivni raspon se prosljeđuje njima, a te usluge stvaraju nove raspone u odnosu na taj raspon.
Sav posao ide kroz Tracer instancu, možete ga dobiti kroz DI mehanizam ili GlobalTracer.get () kao globalnu varijablu ako DI mehanizam ne radi. Prema zadanim postavkama, ako tracer nije inicijaliziran, NoopTracer će se vratiti što ne radi ništa.
Nadalje, trenutni opseg dobiva se od alata za praćenje kroz ScopeManager, novi opseg se stvara iz trenutnog s vezanjem novog raspona, a zatim se kreirani opseg zatvara, što zatvara kreirani raspon i vraća prethodni opseg u aktivno stanje. Opseg je vezan za nit, tako da kod višenitnog programiranja ne smijete zaboraviti prenijeti aktivni raspon u drugu drevu, za daljnju aktivaciju opsega druge niti u odnosu na ovaj raspon.

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 višenitno programiranje također postoji TracedExecutorService i slični omoti koji automatski prosljeđuju trenutni raspon niti kada se pokrenu asinkroni zadaci:

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

Za vanjske http zahtjeve postoji TracingHttpClient

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

Problemi s kojima smo se suočavali

  • Beans i DI ne rade uvijek ako se tracer ne koristi u usluzi ili komponenti Automatski ožičen Tracer možda neće raditi i morat ćete koristiti GlobalTracer.get().
  • Bilješke ne rade ako se ne radi o komponenti ili usluzi ili ako je metoda pozvana iz susjedne metode iste klase. Morate paziti da provjerite što radi i koristiti ručno kreiranje praćenja ako @Traced ne radi. Također možete priložiti dodatni kompajler za java komentare, tada bi trebali raditi posvuda.
  • U starom proljetnom i proljetnom pokretanju, autokonfiguracija opentraing proljetnog oblaka ne radi zbog grešaka u DI-ju, a zatim ako želite da tragovi u proljetnim komponentama rade automatski, to možete učiniti po analogiji s 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
  • Try with resources ne radi u groovyju, morate koristiti try finally.
  • Svaka usluga mora imati vlastiti spring.application.name pod kojim će se tragovi bilježiti. Što znači odvojeno ime za prodaju i test, kako ih ne bi ometali zajedno.
  • Ako koristite GlobalTracer i tomcat, tada sve usluge koje se izvode u ovom tomcatu imaju jedan GlobalTracer, tako da će sve imati isto ime usluge.
  • Kada dodajete tragove metodi, morate biti sigurni da se ne poziva mnogo puta u petlji. Potrebno je dodati jedno zajedničko praćenje za sve pozive, što jamči ukupno vrijeme rada. Inače će se stvoriti prekomjerno opterećenje.
  • Jednom su u jaeger-uiju postavljeni preveliki zahtjevi za veliki broj tragova, a budući da nisu čekali odgovor, učinili su to ponovno. Kao rezultat toga, jaeger-query počeo jesti puno memorije i usporavati elastičnost. Pomoglo je ponovno pokretanje jaeger-queryja

Uzorkovanje, pohranjivanje i pregled tragova

Postoje tri vrste tragovi uzorkovanja:

  1. Const koji šalje i sprema sve tragove.
  2. Probabilistički koji filtrira tragove s određenom vjerojatnošću.
  3. Ratelimiting koji ograničava broj tragova u sekundi. Ove postavke možete konfigurirati na klijentu, bilo na jaeger-agentu ili na sakupljaču. Sada koristimo const 1 u stogu valuatora, budući da nema puno zahtjeva, ali oni dugo traju. U budućnosti, ako će to pretjerano opteretiti sustav, možete ga ograničiti.

Ako koristite cassandru, ona prema zadanim postavkama pohranjuje tragove samo dva dana. Koristimo se elastično pretraživanje a tragovi se pohranjuju za sva vremena i ne brišu se. Za svaki dan kreira se poseban indeks, na primjer jaeger-service-2019-03-04. U budućnosti morate konfigurirati automatsko čišćenje starih tragova.

Za pregled tragova potrebno je:

  • Odaberite uslugu prema kojoj želite filtrirati tragove, na primjer, tomcat7-default za uslugu koja se izvodi u tomcatu i ne može imati vlastiti naziv.
  • Zatim odaberite operaciju, vremenski interval i minimalno vrijeme operacije, na primjer od 10 sekundi, da biste izvršili samo duga izvršenja.
    Service Tracing, OpenTracing i Jaeger
  • Idi na jedan od tragova i vidi što se tamo usporavalo.
    Service Tracing, OpenTracing i Jaeger

Također, ako je neki ID zahtjeva poznat, tada možete pronaći trag prema ovom ID-u putem pretraživanja oznake, ako je ovaj ID zapisan u rasponu praćenja.

Документация

Članci

video

Izvor: www.habr.com

Dodajte komentar