
Meie projektides kasutame mikroteenuste arhitektuuri. Tulemuslikkuse kitsaskohtade ilmnemisel kulub palju aega jälgimisele ja logide analüüsile. Erinevate toimingute ajastuse logimise korral on tavaliselt keeruline mõista, mis viis nende toimingute kutsumiseni, jälgida tegevuste järjestust või ajaintervalli erinevate teenuste vahel.
Käsitöö vähendamiseks otsustasime kasutada ühte jälgimisvahendit. Sellest, kuidas ja milleks saab jälgimist kasutada ning kuidas meie seda tegime, räägib see artikkel.
Milliseid probleeme saab jälgimise abil lahendada
- Leida kitsaskohti tulemuslikkuses nii ühe teenuse sees kui ka kogu täitmispuu ulatuses, kus osalevad kõik teenused. Näiteks:
- Palju lühikesi järjestikuseid kutsungeid teenuste vahel, näiteks geokodeerimine või andmebaasi päringud.
- Pikad ooteajad sisend-väljundis, näiteks andmete edastamine võrgu kaudu või andmete lugemine kettalt.
- Pikkade andmete analüüsimise protsess.
- Pikad operatsioonid, mis vajavad palju CPU ressursse.
- Koodilõigud, mis ei ole lõpptulemuse saavutamiseks vajalikud ja võivad olla eemaldatud või käivitatud viivitusega.
- Visuaalselt mõista, millises järjekorras mida kutsutakse ja mis juhtub, kui tehingut täidetakse.

On näha, et näiteks: päring tuli teenusesse WS -> teenus WS täiendas andmeid teenuse R kaudu -> seejärel saatis päringu teenusesse V -> teenus V laadis palju andmeid teenusest R -> käis teenuses P -> teenus P külastas veel kord teenust R -> teenus V ignoreeris tulemust ja läks teenusesse J -> ja ainult siis tagastas vastuse teenusele WS, samal ajal kui ta jätkas midagi muud taustal arvutamist.
Ilma sellise jälje või üksikasjaliku dokumentatsioonita kogu protsessi kohta on väga keeruline mõista, mis toimub, kui vaadata koodi esmakordselt, ja kood on hajutatud erinevatesse teenustesse ning peidetud hulga binide ja liideste taha. - Teabe kogumine täitevpuu kohta edasiseks viivitamiseks analüüsimiseks. Iga täitmisetapi jooksul võib jäljele lisada teavet, mis on selles etapis saadaval, ja seejärel välja selgitada, millised sisendid viisid sellise stsenaariumi tekkimiseni. Näiteks:
- Kasutaja ID
- Õigused
- Valitud meetodi tüüp
- Logi või teostuse viga
- Jälgimise jälgede muutmine mõõtmete alamkoguks ja edasine analüüs juba mõõtmete kujul.
Mida suudab jälgimine logida. Span
Jälgimises on mõiste span, see on analoog ühele logile konsolis. Spaanil on:
- Nimi, tavaliselt on see meetodi nimi, mida teostati
- Teenuse nimi, milles span genereeriti
- Oma ainulaadne ID
- Mingi meta teave key/value kujul, mida sinna logiti. Näiteks meetodi parameetrid või kas meetod lõppes vea tõttu või mitte
- Selle spaani teostamise algus- ja lõppaeg
- Vanema spaani ID
Iga span saadetakse spaanide kogujale andmete salvestamiseks andmebaasi, et hiljem vaadata, kui see on lõpetanud oma teostamise. Edasi saab üles ehitada kõigi spaanide puu, ühendades vanema ID järgi. Analüüsimisel saab näiteks leida kõik spaanid mingis teenuses, mis võtsid rohkem kui mingit aega. Edasi liikudes saab vaadata konkreetset spaani, näha kõiki puu ülal ja all seda spaani.

Opentrace, Jagger ja kuidas me seda oma projektides rakendasime
On olemas üldine standard , mis kirjeldab, kuidas ja mida tuleks koguda, ilma et see oleks seotud konkreetse rakenduse rakendamisega mõnes keeles. Näiteks Java-s käib kogu jälgimisega töö läbi Opentrace'i ühise API, mille all võib peituda näiteks Jaeger või tühi vaikimisi rakendus, mis ei tee midagi.
Meie kasutame kui Opentrace'i rakendust. See koosneb mitmest komponendist:

- Jaeger-agent — kohalik agent, mis tavaliselt töötab igas masinas ja kuhu logivad teenused lokaalses vaikimisi sadamas. Kui agenti pole, siis on selle masina kõikide teenuste jälgimine tavaliselt välja lülitatud.
- Jaeger-kogujaja — selle kaudu saadavad kõik agendid kogutud jälgimised, ning see salvestab need valitud andmebaasi.
- Andmebaas — nende eelistatud on Cassandra, kuid meie kasutame Elasticsearchi, olemas on teostused ka paari muu andmebaasi jaoks ja mälus olev rakendus, mis ei salvesta ühtegi andmeid kettale.
- Jaeger-küsimine — see on teenus, mis tutvustab andmebaasi ja tagastab juba kogutud jälgimised analüüsiks.
- Jaeger-kasutajaliides — see on veebiliides jälgimiste otsimiseks ja vaatamiseks, see eeldab juurdepääsu jaeger-küsimisele.

Eraldi komponendina võib välja tuua opentrace jaeger rakenduse erinevates programmeerimiskeeltes, mille kaudu saadetakse spaanid jaeger-agendile.
piirdub io.opentracing.Tracer liidese rakendamisega, mille järel kõik jäljed saadetakse selle kaudu tegelikku agendile.

Samuti saab Springi komponente ühendades kasutada ja Jaegeri rakendust mis konfigureerib automaatselt jälgimise kõikidele komponentide kaudu, näiteks http päringutele kontrollereid, andmebaasi päringutele jdbc kaudu jne.
Jälgede logimine Java-s
Kõrgemal tasemel peab olema loodud esimene Span, see võib olla automaatselt loodud näiteks Springi kontrolleri poolt päringu saamisel või käsitsi, kui sellist ei ole. Edasi edastatakse see madalamale Scope'i. Kui mõni allpool olev meetod soovib lisada Span'i, siis võtab ta praeguse activeSpan'i Scope'ist, loob uue Span'i ja ütleb, et selle vanem on saadud activeSpan, ning teeb uue Span'i aktiivseks. Välist teenuseid kutsudes antakse neile üle praegune aktiivne spaan, ning need teenused loovad uusi spaan'e, mis on seotud selle spaaniga.
Kogu töö toimub Tracer'i kaudu, mille saab DI mehhanismi kaudu või GlobalTracer.get() kaudu, kui DI mehhanism ei toimi. Vaikimisi, kui tracerit ei ole initseeritud, tagastatakse NoopTracer, mis ei tee midagi.
Edasi saab tracer'i kaudu ScopeManager'ist praeguse scope'i, luuakse uus scope praegusest koos uue spaaniga, seejärel suletakse loodud Scope, mis sulgeb loodud spaani ja tagastab aktiivseks varasema Scope'i. Scope on seotud lõimega, seega tuleb mitme lõime programmeerimisel meeles pidada, et edastada aktiivne spaan teise lõime juurde, et aktiveerida teise lõime Scope, millel on seos selle spaaniga.
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)) {
...
}
});
}
}Kuna mitme hüjeni programmimiseks on samuti olemas TracedExecutorService ja sarnased mähised, mis edastavad automaatselt praeguse spani lõime, kui töötatakse asünkroonselt:
private ExecutorService executor = new TracedExecutorService(
Executors.newFixedThreadPool(10), GlobalTracer.get()
);Väliste http päringute jaoks on olemas
HttpClient httpClient = new TracingHttpClientBuilder().build();Probleemid, millega me silmitsi seisame
- Binaarsed ja DI ei tööta alati, kui tracerit ei kasutata teenuses või komponendis, siis Tracer ei pruugi töötada ja peate kasutama GlobalTracer.get().
- Annotatsioonid ei tööta, kui see ei ole komponent või teenus, või kui meetodi kutsumine toimub sama klassi naabermeetodist. Tuleb olla ettevaatlik, kontrollida, mida kasutatakse, ja kasutada käsitsi jälgimise loomist, kui @Traced ei tööta. Samuti võib lisada täiendava kompilaatori Java annotatsioonide jaoks, siis peaksid need töötama igal pool.
- Vanades Spring ja Spring Boot versioonides ei tööta OpenTracing auto-konfiguratsioon Spring Cloudis DI vigade tõttu. Kui soovite, et jälgimised töötaksid automaatselt Springi komponentides, siis saate toimida analoogselt
- Groovy's ei tööta try with resources; tuleb kindlasti kasutada try finally.
- Igale teenusele tuleb määrata oma spring.application.name, mille alusel jälgimised logitakse. Lisaks peab olema eraldi nimi tootmis- ja testkeskkonna jaoks, et need omavahel ei segaks.
- Kui kasutada GlobalTracerit ja Tomcat'i, siis kõik selles Tomcat'is käivitatud teenused jagavad üht GlobalTracerit, seega on neil kõigil sama teenuse nimi.
- Tõrgete lisamisel meetodisse tuleb veenduda, et see ei kutsutaks tsüklis liiga palju kordi. Tuleb lisada üks ühine jälgimine kõigi kutsumiste jaoks, mis logib koguaeg. Vastasel juhul tekib liigset koormust.
- Kunagi jaeger-ui-s tegime liiga suuri päringuid suure hulga jälgede kohta ja kuna me ootamist ei kannatanud, siis tegime uuesti. Tulemusena hakkas jaeger-query tarbima palju mälu ja aeglustama elastikut. Aitas jaeger-query taaskäivitamine.
Proovide võtmine, säilitamine ja jälgede vaatamine.
On kolm tüüpi. :
- Const, mis saadab ja salvestab kõik jäljed.
- Probabilistic, mis filtreerib jälgi mõne määratud tõenäosusega.
- Ratelimiting, mis piirab jälgede arvu sekundis. Need parameetrid saab seadistada kliendis, jaeger-agent'is või kollektoris. Praegu kasutatakse meie valideerimise stegis const 1, kuna päringuid ei ole liiga palju, kuid need kestavad kaua. Edasi, kui see tekitab süsteemile liigset koormust, saab piirata.
Kui kasutada cassandrat, salvestab see vaikimisi jäljed ainult kaheks päevaks. Meil on kasutusel. jaeger'i jäljed salvestatakse kogu aeg ja ei kustutata. Iga päeva jaoks luuakse eraldi indeks, näiteks jaeger-service-2019-03-04. Edasi tuleb seadistada automaatne vanade jälgede puhastamine.
Jälgede vaatamiseks tuleb:
- Valida teenus, mille järgi soovite jälgi filtreerida, näiteks tomcat7-default teenuse jaoks, mis on käivitatud Tomcatis ega saa omada oma nime.
- Edasi tuleb valida toiming, ajavahemik ja minimaalne operatiiviaeg, näiteks alates 10 sekundist, et saada ainult pikki täitmisi.

- Siis liikuge ühte jälge ja vaadake, mis seal takerdus.

Kui on tuntud mõni päringu id, saab ka selle id järgi jälje leida siltide otsingu kaudu, kui see id logitakse jälje spaani.
Dokumentatsioon
- Opentracingi dokumentatsioon
- Jaegeri dokumentatsioon
- Jaegeri Java ühendamine
- Spring Opentracing ühendamine
Artiklid
- Jaeger Opentracing ja mikroteenused reaalses projektis PHP ja Golangi peal
- Evolving Distributed Tracing at Uber Engineering
- Jaegeri agendi käivitamine füüsilisel masinal
Video
- Kuidas me kasutasime Jaegerit ja Prometheust, et pakkuda vilkuvalt kiireid kasutaja päringuid — Bryan Boreham
- Sissejuhatus: Jaeger — Yuri Shkuro, Uber & Pavol Loffay, Red Hat
- Serghei Iakovlev, "Väike lugu suurest võidust: OpenTracing, AWS ja Jaeger"
Allikas: habr.com



