Praćenje usluga, OpenTracing i Jaeger

Praćenje usluga, OpenTracing i Jaeger

Mi koristimo mikroservisnu arhitekturu u našim projektima. Kada se pojave uska grla u performansama, mnogo vremena se troši na praćenje i raščlanjivanje dnevnika. Prilikom evidentiranja vremena pojedinačnih operacija u datoteku dnevnika, obično je teško razumjeti šta je dovelo do pozivanja ovih operacija, pratiti slijed radnji ili vremenski pomak jedne operacije u odnosu na drugu u različitim uslugama.

Kako bismo minimizirali ručni rad, odlučili smo koristiti jedan od alata za praćenje. O tome kako i zašto možete koristiti praćenje i kako smo to uradili, biće reči u ovom članku.

Koji se problemi mogu riješiti praćenjem

  1. Pronađite uska grla u performansama i unutar jedne usluge i u cijelom stablu izvršenja između svih usluga koje učestvuju. Na primjer:
    • Mnogi kratki uzastopni pozivi između usluga, na primjer, geokodiranju ili bazi podataka.
    • Duga I/O čekanja, kao što su mrežni prijenosi ili čitanje diska.
    • Dugo raščlanjivanje 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 kojim redoslijedom se ono zove i šta se događa kada se operacija izvede.
    Praćenje usluga, 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 sa R servis -> otišao na P servis -> P servis je ponovo otišao na servis R -> servis V je zanemario rezultat i otišao na servis J -> i tek onda vratio odgovor servisu WS, dok je nastavio da izračunava nešto drugo u pozadinu.
    Bez takvog traga ili detaljne dokumentacije za ceo proces, veoma je teško razumeti šta se dešava kada prvi put pogledate kod, a kod je razbacan po različitim servisima i skriven iza gomile binova i interfejsa.
  3. Prikupljanje informacija o stablu izvršenja za naknadnu odgođenu analizu. U svakoj fazi izvršenja možete dodati informacije u praćenje koje su dostupne u ovoj fazi, a zatim otkriti koji su ulazni podaci doveli do sličnog scenarija. Na primjer:
    • Korisnički broj
    • Prava
    • Vrsta odabrane metode
    • Greška u zapisniku ili izvršenju
  4. Pretvaranje tragova u podskup metrika i dalja analiza već u obliku metrike.

Koji trag se može evidentirati. Raspon

U praćenju postoji koncept raspona, ovo je analog jednog dnevnika, do konzole. Banja ima:

  • Ime, obično ime metode koja je izvršena
  • Naziv usluge u kojoj je generiran raspon
  • Vlastiti jedinstveni ID
  • Neka vrsta meta informacija u obliku ključa/vrijednosti koji je u nju prijavljen. Na primjer, parametri metode ili metoda je završila s greškom ili ne
  • Vrijeme početka i završetka za ovaj raspon
  • ID roditeljskog raspona

Svaki raspon se šalje sakupljaču raspona kako bi se pohranio u bazu podataka za kasniji pregled čim završi svoje izvršenje. U budućnosti, možete izgraditi stablo svih raspona povezivanjem preko roditeljskog ID-a. Kada analizirate, možete pronaći, na primjer, sve raspone u nekom servisu za koje je trebalo više vremena. Nadalje, odlaskom na određeni raspon, vidite cijelo stablo iznad i ispod ovog raspona.

Praćenje usluga, OpenTracing i Jaeger

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

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

Praćenje usluga, OpenTracing i Jaeger

  • Jaeger-agent je lokalni agent koji je obično instaliran na svakom stroju i usluge su prijavljene na njega na lokalnom zadanom portu. Ako nema agenta, onda su tragovi svih usluga na ovoj mašini 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 casandra, 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 ide u bazu podataka i vraća već prikupljene tragove na analizu
  • Jaeger-ui je web sučelje za pretraživanje i pregled tragova, ide na jaeger-query

Praćenje usluga, OpenTracing i Jaeger

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

Praćenje usluga, OpenTracing i Jaeger

Također za komponentu opruge, možete spojiti opentracing-spring-cloud-starter i 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 do kontrolera, zahtjeve bazi podataka preko jdbc-a, itd.

Prati prijavu u Javu

Negdje na najvišem nivou mora se kreirati prvi Span, to se može uraditi automatski, na primjer, pomoću kontrolera opruge kada se primi zahtjev ili ručno ako ga nema. Zatim se prenosi kroz donji opseg. Ako bilo koja metoda ispod želi da doda Span, ona uzima trenutni activeSpan iz opsega, kreira novi raspon i kaže da je njegov roditelj rezultujući activeSpan, i čini novi raspon aktivnim. Prilikom pozivanja eksternih usluga, trenutni aktivni raspon se prosljeđuje njima, a te usluge kreiraju nove raspone u odnosu na ovaj raspon.
Sav posao ide kroz instancu Tracera, možete je dobiti preko DI mehanizma, ili GlobalTracer.get () kao globalnu varijablu ako DI mehanizam ne radi. Podrazumevano, ako tracer nije inicijaliziran, NoopTracer će se vratiti što ne radi ništa.
Dalje, trenutni opseg se dobija iz tracera kroz ScopeManager, novi opseg se kreira od trenutnog sa povezivanjem novog opsega, a zatim se kreirani opseg zatvara, što zatvara kreirani opseg i vraća prethodni opseg u aktivnom stanju. Opseg je vezan za nit, tako da kod višenitnog programiranja ne smijete zaboraviti prenijeti aktivni raspon u drugu nit, radi dalje aktivacije 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 programiranje s više niti, postoji i TracedExecutorService i slični omoti koji automatski prosljeđuju trenutni raspon u nit kada se pokreću asinkroni zadaci:

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

Za eksterne http zahtjeve postoji TracingHttpClient

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

Problemi sa kojima smo se suočili

  • Beans i DI ne rade uvijek ako se tracer ne koristi u servisu ili komponenti Autowired Tracer možda neće raditi i morat ćete koristiti GlobalTracer.get().
  • Napomene ne rade ako nije komponenta ili usluga, ili ako je metoda pozvana iz susjedne metode iste klase. Morate biti oprezni da provjerite šta radi i koristite ručno kreiranje praćenja ako @Traced ne radi. Također možete priložiti dodatni kompajler za java napomene, tada bi trebali raditi svuda.
  • U starom spring i spring boot-u, opentraing spring cloud autokonfiguracija ne radi zbog grešaka u DI, onda ako želite da tragovi u komponentama spring rade automatski, možete to učiniti analogno sa 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
  • Pokušajte sa resursima ne radi u groovy, morate koristiti try finally.
  • Svaki servis mora imati svoje spring.application.name pod kojim će se tragovi evidentirati. Što znači odvojeno ime za prodaju i test, kako ih ne bi ometali zajedno.
  • Ako koristite GlobalTracer i tomcat, onda sve usluge koje rade 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 jedan zajednički trag za sve pozive, što garantuje ukupno vreme rada. U suprotnom će se stvoriti višak opterećenja.
  • Jednom u jaeger-ui-u su napravljeni preveliki zahtjevi za velikim brojem tragova, a pošto nisu čekali odgovor, učinili su to ponovo. Kao rezultat toga, jaeger-query je počeo jesti mnogo memorije i usporavati elastičnost. Pomoglo ponovnim pokretanjem jaeger-query-a

Uzorkovanje, pohranjivanje i pregled tragova

Postoje tri vrste uzorkovanje tragova:

  1. Const koji šalje i sprema sve tragove.
  2. Probabilistički koji filtrira tragove s nekom zadatom vjerovatnoćom.
  3. Ograničavanje brzine koje ograničava broj tragova u sekundi. Ove postavke možete konfigurirati na klijentu, bilo na jaeger-agentu ili na kolektoru. Sada koristimo const 1 u steku procenjivača, pošto nema mnogo zahteva, ali zahtevaju mnogo vremena. U budućnosti, ako će to predstavljati preveliko opterećenje na sistemu, možete ga ograničiti.

Ako koristite cassandru, tada ona po defaultu pohranjuje tragove samo dva dana. Koristimo elastična pretraga a tragovi se pohranjuju za sva vremena i ne brišu se. Za svaki dan se kreira poseban indeks, na primjer jaeger-service-2019-03-04. U budućnosti ćete morati konfigurirati automatsko čišćenje starih tragova.

Da biste vidjeli tragove potrebno vam je:

  • Odaberite uslugu prema kojoj želite filtrirati tragove, na primjer, tomcat7-default za uslugu koja se izvodi u tomcat-u i ne može imati svoje ime.
  • Zatim odaberite operaciju, vremenski interval i minimalno vrijeme rada, na primjer od 10 sekundi, da biste poduzeli samo duga izvršavanja.
    Praćenje usluga, OpenTracing i Jaeger
  • Idite na jedan od tragova i vidite šta se tamo usporava.
    Praćenje usluga, OpenTracing i Jaeger

Također, ako je neki id zahtjeva poznat, onda možete pronaći trag po ovom ID-u kroz pretragu tagova, ako je ovaj id prijavljen u rasponu traga.

Dokumentacija

Članci

Video

izvor: www.habr.com

Dodajte komentar