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
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.
Jasno razumjeti u kojem slijedu što se zove i što se događa kada se operacija izvodi.
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.
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
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.
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:
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
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.
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.
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()
);
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.
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
Probabilistički koji filtrira tragove s određenom vjerojatnošću.
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.
Idi na jedan od tragova i vidi što se tamo usporavalo.
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.