Teenuste jÀlgimine, OpenTracing ja Jaeger

Teenuste jÀlgimine, OpenTracing ja Jaeger

Meie projektides kasutame mikroteenuste arhitektuuri. JĂ”udlusprobleemide ilmnemisel kulub palju aega jĂ€lgimisele ja logide analĂŒĂŒsimisele. Aegade logimine eri operatsioonide jaoks logifaili seab tavaliselt probleeme, kuna on keeruline mĂ”ista, mis viis nende operatsioonide kĂ€ivitamiseni, jĂ€lgida toimingute jĂ€rjestust vĂ”i ajastuse nihkumist ĂŒhe operatsiooni suhtes teise vahel erinevates teenustes.

KĂ€sitöö vĂ€hendamiseks otsustasime kasutada ĂŒhte jĂ€lgimisriista. Sellest, kuidas ja miks jĂ€lgimist kasutada ning kuidas meie seda tegime, rÀÀgib see artikkel.

Milliseid probleeme saab jÀlgimisega lahendada

  1. Leida kitsaskohti jĂ”udluses nii ĂŒhe teenuse sees kui ka kogu teostuse puus kĂ”igi osalevate teenuste vahel. NĂ€iteks:
    • Palju lĂŒhikesi jĂ€rjestikuseid kutseid teenuste vahel, nĂ€iteks geokodeerimise vĂ”i andmebaasi pĂ€ringute puhul.
    • Pikad ootamised sisendi / vĂ€ljundi osas, nĂ€iteks andmete edastamine vĂ”rgus vĂ”i kettalt lugemine.
    • Pikk andmete parsimine.
    • Pikad operatsioonid, mis nĂ”uavad CPU-d.
    • Koodijupid, mis ei ole vajalikud lĂ”pptulemuse saamiseks ja vĂ”iksid olla eemaldatud vĂ”i viidatud hiljem.
  2. Selgelt mÔista, millises jÀrjekorras asjad aset leiavad ja mis toimub, kui operatsioon kÀivitub.
    Teenuste jÀlgimine, OpenTracing ja Jaeger
    NÀha, et nÀiteks pÀring tuli teenusesse WS -> teenus WS tÀiendas andmeid teenuse R kaudu -> seejÀrel saatis pÀringu teenusele V -> teenus V laadis palju andmeid teenusest R -> kÀidi teenuses P -> teenus P kÀis veel kord teenuses R -> teenus V ignoreeris tulemust ja lÀks teenusesse J -> ja alles seejÀrel naasis vastus teenusele WS, samal ajal jÀtkates midagi muud taustal arvutamist.
    Ilma sellise jĂ€lgimata vĂ”i ĂŒksikasjaliku dokumentatsioonita kogu protsessi kohta on esmakordselt koodi vaadates vĂ€ga keeruline mĂ”ista, mis toimub, ja kood on hajutatud erinevatesse teenustesse ning peidetud mitmete beani ja liideste taha.
  3. Teostuse puu teabe kogumine edasiseks analĂŒĂŒsiks. Igas teostusetapis saab jĂ€lgisse lisada teavet, mis on sellel etapil saadaval, ja hiljem tuvastada, millised sisendi andmed viisid antud stsenaariumi ilmnemiseni. NĂ€iteks:
    • Kasutaja ID
    • Õigused
    • Valitud meetodi tĂŒĂŒp
    • Log vĂ”i töötluse viga
  4. KĂ€iguteede muutmine alameetriks ja edasine analĂŒĂŒs metrikate kujul.

Mida suudab logida jÀlgimine. Span

JĂ€lgimises on mĂ”isted span, mis on analoog ĂŒhele logile, konsoolis. Spanil on:

  • Nimi, tavaliselt meetodi nimi, mis viidi lĂ€bi
  • Teenuse nimi, milles span genereeriti
  • Oma ainulaadne ID
  • MĂ”ni meta teave key/value kujul, mis on sinna logitud. NĂ€iteks meetodi parameetrid vĂ”i see, kas meetod lĂ”ppes veaga vĂ”i mitte
  • Span'i algus- ja lĂ”ppkja aeg
  • Vanema span'i ID

Iga span saadetakse spanide kollektsionÀÀrile, et salvestada see andmebaasi edasiseks vaatamiseks, niipea kui see on oma tĂ€itmise lĂ”petanud. Hiljem on vĂ”imalik ehitada kĂ”igi spanide puu, ĂŒhendades neid vanema ID jĂ€rgi. AnalĂŒĂŒsi kĂ€igus on vĂ”imalik leida nĂ€iteks kĂ”ik spandid mĂ”nes teenuses, mis vĂ”tsid rohkem aega kui teatud aeg. Edasi liikudes saab konkreetse span'i juurde minnes nĂ€ha kĂ”iki puu osi selle span'i kohal ja all.

Teenuste jÀlgimine, OpenTracing ja Jaeger

Opentrace, Jaeger ja kuidas me seda oma projektides rakendasime

On olemas ĂŒldine standard Opentrace, mis kirjeldab, kuidas ja mida peab koguma, mitte seondudes jĂ€lgimise konkreetse teostusega mĂ”nes keeles. NĂ€iteks Java-s kĂ€ib kogu jĂ€lgimistöötamine lĂ€bi ĂŒldise API Opentrace, ja selle all vĂ”ib peituda nĂ€iteks Jaeger vĂ”i tĂŒhi vaikimisi teostus, mis ei tee midagi.
Meie sĂŒsteem kasutab Jaeger kui Opentrace'i teostust. See koosneb mitmest komponendist:

Teenuste jÀlgimine, OpenTracing ja Jaeger

  • Jaeger-agent — kohalik agent, mis on tavaliselt igas masinas ja kuhu logivad teenused kohalikke vaikimisi porte. Kui agenti pole, siis on kĂ”igi selle masina teenuste jĂ€lgimised tavaliselt vĂ€lja lĂŒlitatud
  • Jaeger-kollektor — kuhu kĂ”ik agendid saadavad kogutud jĂ€lgimised ning mis salvestab need valitud andmebaasi
  • Andmebaas — nende eelistatuim on Cassandra, kuid meie kasutame Elasticsearchi, on olemas teostusi ka mĂ”ne muu andmebaasi ja mĂ€lu teostuse jaoks, mis ei salvestada midagi kettale
  • Jaeger-kĂŒsimus — see on teenus, mis lĂ€heb andmebaasi ja toob juba kogutud jĂ€lgimised analĂŒĂŒsiks
  • Jaeger-ui — see on veebirakendus jĂ€lgimiste otsimiseks ja vaatamiseks, mis lĂ€heb jaeger-kĂŒsimusse

Teenuste jÀlgimine, OpenTracing ja Jaeger

Eraldi komponendina vÔib nimetada opentrace jaeger'i teostust konkreetsete keelte jaoks, mille kaudu span'id saadetakse jaeger-agenti.
Jageri ĂŒhendamine Java-s see on nĂ€htav, et rakendada liidest io.opentracing.Tracer, mille jĂ€rel kĂ”ik jĂ€ljed suunatakse lĂ€bi selle tegelikule agentile.

Teenuste jÀlgimine, OpenTracing ja Jaeger

Samuti saab Springi komponente ĂŒhendada opentracing-spring-cloud-starter ja Jaegeri teostus opentracing-spring-jaeger-cloud-starter , mis konfigureerib automaatselt jĂ€lgimise kĂ”igile, mis lĂ€bib neid komponente, nĂ€iteks HTTP-pĂ€ringud kontrolleritesse, andmebaasi pĂ€ringud lĂ€bi jdbc jne.

JĂ€lgede logimine Java-s

Kusagil kÔige kÔrgeimal tasemel peaks olema loodud esimene Span, see vÔib toimuda automaatselt nÀiteks Springi kontrolleri kaudu pÀringu saamisel vÔi kÀsitsi, kui sellist ei ole. Edasi edastatakse see alla Scope'i. Kui mÔni allolev meetod soovib lisada Span'i, vÔtab ta Scope'ist praeguse activeSpan'i, loob uue Span'i ja mÀÀrab, et tema vanem on saadud activeSpan, ning teeb uue Span'i aktiivseks. VÀlistele teenustele edastatakse praegune aktiivne span ja need teenused loovad uued spanid, mis on seotud sellega.
Kogu töö kÀib Tracer'i nÀite kaudu, mille saab saada DI mehhanismi abil vÔi GlobalTracer.get() kui globaalse muutujana, kui DI mehhanism ei tööta. Kui tracer ei ole algselt initsialiseeritud, naaseb NoopTracer, mis ei tee midagi.
SeejĂ€rel vĂ”etakse tracer'ist lĂ€bi ScopeManager'i praegune scope, luuakse uus scope praegusest, side uue span'iga, ja seejĂ€rel suletakse loodud Scope, mis sulgeb loodud span'i ja taastab varasema Scope'i aktiivseks olekuks. Scope on seotud ĂŒhe niidiga, seetĂ”ttu tuleb mitme niidi programmeerimisel meeles pidada, et edastada aktiivne span teisele niidile, et aktiveerida teise niidi Scope, mis on seotud selle span'iga.

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)) {
        // Tee asju.
    } 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: aktiveeri span tagasi callbackis, edastades true
            // startActive() juhul, kui span peab olema lÔpetatud.
            try (Scope scope = tracer.scopeManager().activate(span, false)) {
                ...
            }
        });
    }
}

Mitme lĂ”ime programmeerimiseks on olemas TracedExecutorService ja sarnased wrapper'id, mis edastavad automaatselt praeguse spani lĂ”ime, kui asĂŒnkroonsed ĂŒlesanded kĂ€ivitatakse:

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

VÀliste http pÀringute jaoks on olemas TracingHttpClient

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

Probleemid, millega me silmitsi seisame

  • Beendid ja DI ei pruugi alati töötada, kui tracerit ei kasutata teenuses vĂ”i komponendis, siis Autowired Tracer ei pruugi töötada ja tuleb kasutada GlobalTracer.get().
  • Annotatsioonid ei tööta, kui see ei ole komponent vĂ”i teenus, vĂ”i kui meetodi kutsumine toimub sama klassi naabermetodist. Tuleb olla ettevaatlik, kontrollida, mis töötab, ja kasutada manuaalset jĂ€lgimise loomist, kui @Traced ei tööta. Samuti saab lisada tĂ€iendava kompilaatori java annotatsioonide jaoks, siis peaks need töötama igal pool.
  • Vanades spring ja spring boot versioonides ei toimi opentracing spring cloud automaatne seadistamine DI vigade tĂ”ttu, seega, kui soovite, et jĂ€lgimised komponentides automaatselt töötaksid, siis vĂ”ib teha sarnaselt 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
  • Groovy's ei toimi try with resources, tuleb kindlasti kasutada try finally.
  • Iga teenuse kohta tuleb mÀÀrata oma spring.application.name, mille alusel jĂ€lgimised logitakse. Eraldi nimi tootmises ja testimises, et nad koos ei seguneks.
  • Kui kasutada GlobalTracerit ja tomcat, siis kĂ”ik teenused, mis on selles tomcat'is kĂ€ivitatud, jagavad ĂŒhte GlobalTracerit, seega on kĂ”igil sama teenuse nimi.
  • JĂ€lgimiste lisamisel meetodisse tuleb olla kindel, et seda ei kutsuta tsĂŒklis liiga sageli. Tuleb lisada ĂŒks ĂŒhine jĂ€lgimine kĂ”igile kutsetele, mis logib koguaegade kokku. Vastasel juhul tekib liigset koormust.
  • Kord, kui jaeger-ui's tehti liiga suuri pĂ€ringuid suure hulga jĂ€lgimiste kohta ja kuna ei oodatud vastust, tehti see uuesti. Tulemuseks oli, et jaeger-query hakkas kasutama palju mĂ€lu ja aeglustas elastikut. Taastas jaeger-query'i taaskĂ€ivitamine aitas.

JÀlgimiste proovivÔtt, salvestamine ja vaatamine

On kolm tĂŒĂŒpi jĂ€lgimise proovivĂ”tt:

  1. Const, mis saadab ja salvestab kÔik jÀlgimised.
  2. Probabilistic, mis filtreerib jÀlgimisi kindla tÔenÀosusega.
  3. Ratelimiting, mis piirab tehingute arvu sekundis. Nende parameetreid saab seadistada kliendil, kas jaeger-agendis vĂ”i kogujas. Praegu on meil rakendustes kasutusel const 1, kuna pĂ€ringute arv ei ole liiga suur, kuid need vĂ”tavad aega. Edasi, kui see sĂŒsteemile liiga palju koormust tekitab, saab piirata.

Kui kasutada cassandrat, siis salvestab see tehingud vaikimisi ainult kaheks pÀevaks. Meie puhul kasutatakse elasticsearch ja tehingud salvestatakse kogu aeg ja ei kustutata. Igal pÀeval luuakse eraldi indeks, nÀiteks jaeger-service-2019-03-04. Tulevikus tuleb seadistada automaatne vana tehingu kustutamine.

Tehingute vaatamiseks tuleks:

  • Valida teenus, mille pĂ”hjal soovid tehinguid filtreerida, nĂ€iteks tomcat7-default teenuse puhul, mis on kĂ€ivitatud tomcat-is ega saa omada oma nime.
  • SeejĂ€rel valida operatsioon, ajavahemik ja minimaalne operatsiooni aeg, nĂ€iteks alates 10 sekundist, et vĂ”tta ainult pikki tĂ€itmisperioode.
    Teenuste jÀlgimine, OpenTracing ja Jaeger
  • Liikuda ĂŒhe tehingu juurde ja vaadata, mis seal takistab.
    Teenuste jÀlgimine, OpenTracing ja Jaeger

Samuti, kui on teada mÔni pÀringu ID, siis saab leida tehingu selle ID kaudu, otsides silte, kui see ID logitakse tehingu span'i.

Dokumentatsioon

Artiklid

Video

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster