Service Tracing, OpenTracing kaj Jaeger

Service Tracing, OpenTracing kaj Jaeger

Ni uzas mikroservan arkitekturon en niaj projektoj. Kiam rezultaj proplempunktoj okazas, multe da tempo estas elspezita monitorante kaj analizante protokolojn. Dum enhakado de la tempoj de individuaj operacioj al protokoldosiero, estas kutime malfacile kompreni kio kondukis al la alvoko de ĉi tiuj operacioj, por spuri la sekvencon de agoj aŭ la tempoŝanĝo de unu operacio relative al alia en malsamaj servoj.

Por minimumigi manan laboron, ni decidis uzi unu el la spuriloj. Pri kiel kaj kial vi povas uzi spuradon kaj kiel ni faris ĝin, kaj estos diskutita en ĉi tiu artikolo.

Kiajn problemojn oni povas solvi per spurado

  1. Trovu rendimentajn proplempunktojn kaj ene de ununura servo kaj en la tuta ekzekuta arbo inter ĉiuj partoprenantaj servoj. Ekzemple:
    • Multaj mallongaj sinsekvaj vokoj inter servoj, ekzemple, al geokodigo aŭ al datumbazo.
    • Longaj I/O-atendoj, kiel retaj translokigoj aŭ diskolegoj.
    • Longa analizado de datumoj.
    • Longaj operacioj postulantaj CPU.
    • Sekcioj de kodo kiuj ne estas bezonataj por akiri la finan rezulton kaj povas esti forigitaj aŭ prokrastitaj.
  2. Klare komprenu en kia sinsekvo, kion oni nomas kaj kio okazas kiam la operacio estas farita.
    Service Tracing, OpenTracing kaj Jaeger
    Videblas, ke ekzemple la Peto venis al la WS-servo -> la WS-servo aldonis datumojn per la R-servo -> poste sendis peton al la V-servo -> la V-servo ŝargis multajn datumojn el la R. servo -> iris al la servo P -> la servo P denove iris al servo R -> servo V ignoris la rezulton kaj iris al servo J -> kaj nur tiam resendis la respondon al servo WS, dum daŭre kalkulis ion alian en la servo. fono.
    Sen tia spuro aŭ detala dokumentado por la tuta procezo, estas tre malfacile kompreni, kio okazas kiam oni rigardas la kodon la unuan fojon, kaj la kodo estas disigita tra malsamaj servoj kaj kaŝita malantaŭ amaso da rubujoj kaj interfacoj.
  3. Kolekto de informoj pri la ekzekuta arbo por posta prokrastita analizo. En ĉiu etapo de ekzekuto, vi povas aldoni informojn al la spuro, kiu estas disponebla en ĉi tiu etapo, kaj tiam eltrovi kiajn enigajn datumojn kondukis al simila scenaro. Ekzemple:
    • Uzanto ID
    • Rajtoj
    • Tipo de elektita metodo
    • Ensalutu aŭ ekzekuta eraro
  4. Transformi spurojn en subaron de metrikoj kaj plian analizon jam en formo de metrikoj.

Kia spuro povas ensaluti. Spano

En spurado ekzistas la koncepto de interspaco, ĉi tio estas analogo de unu ŝtipo, al la konzolo. La banurbo havas:

  • Nomo, kutime la nomo de la metodo kiu estis efektivigita
  • La nomo de la servo en kiu la interspaco estis generita
  • Propra unika identigilo
  • Ia meta-informo en la formo de ŝlosilo/valoro kiu estis ensalutinta en ĝi. Ekzemple, metodoparametroj aŭ la metodo finiĝis per eraro aŭ ne
  • Komencaj kaj finaj tempoj por ĉi tiu daŭro
  • Gepatra span ID

Ĉiu interspaco estas sendita al la span kolektanto por esti stokita en la datumbazo por pli posta revizio tuj kiam ĝi kompletigis sian ekzekuton. En la estonteco, vi povas konstrui arbon de ĉiuj interspacoj per konekto per gepatra id. Analizante, vi povas trovi, ekzemple, ĉiujn interspacojn en iu servo, kiuj daŭris pli ol iom da tempo. Plue, irante al specifa interspaco, vidu la tutan arbon super kaj sub ĉi tiu interspaco.

Service Tracing, OpenTracing kaj Jaeger

Opentrace, Jagger kaj kiel ni efektivigis ĝin por niaj projektoj

Estas komuna normo malferma spuro, kiu priskribas kiel kaj kio devus esti kolektita, sen esti ligita per spurado al specifa efektivigo en iu ajn lingvo. Ekzemple, en Java, ĉiu laboro kun spuroj estas farita per la komuna Opentrace API, kaj sub ĝi, ekzemple, Jaeger aŭ malplena defaŭlta efektivigo kiu faras nenion povas esti kaŝitaj.
Ni uzas Jaeger kiel efektivigo de Opentrace. Ĝi konsistas el pluraj komponantoj:

Service Tracing, OpenTracing kaj Jaeger

  • Jaeger-agento estas loka agento kiu estas kutime instalita sur ĉiu maŝino kaj servoj estas ensalutitaj en ĝi sur la loka defaŭlta haveno. Se ne ekzistas agento, tiam spuroj de ĉiuj servoj sur ĉi tiu maŝino estas kutime malŝaltita
  • Jaeger-kolektanto - ĉiuj agentoj sendas kolektitajn spurojn al ĝi, kaj ĝi metas ilin en la elektitan datumbazon
  • La datumbazo estas ilia preferata Cassandra, sed ni uzas elasticsearch, ekzistas efektivigoj por kelkaj aliaj datumbazoj kaj en-memora efektivigo, kiu ŝparas nenion al disko.
  • Jaeger-query estas servo kiu iras al la datumbazo kaj resendas jam kolektitajn spurojn por analizo
  • Jaeger-ui estas retinterfaco por serĉi kaj vidi spurojn, ĝi iras al jaeger-query

Service Tracing, OpenTracing kaj Jaeger

Aparta komponento povas esti nomita la efektivigo de opentrace jaeger por specifaj lingvoj, tra kiuj interspacoj estas senditaj al jaeger-agento.
Konektante Jagger en Java venas al efektivigo de la io.opentracing.Tracer interfaco, post kiu ĉiuj spuroj tra ĝi flugos al la reala agento.

Service Tracing, OpenTracing kaj Jaeger

Ankaŭ por la printempa komponanto, vi povas konekti opentracing-printempa-nubo-startilo kaj efektivigo de Jaeger opentracing-printempo-jaeger-nubo-startilo kiu aŭtomate agordos spuradon por ĉio, kio pasas tra ĉi tiuj komponantoj, ekzemple http-petoj al regiloj, petoj al la datumbazo per jdbc, ktp.

Spuroj ensalutantaj en Java

Ie ĉe la supra nivelo, la unua Span devas esti kreita, tio povas esti farita aŭtomate, ekzemple, de la printempa regilo kiam peto estas ricevita, aŭ permane se ekzistas neniu. Ĝi tiam estas elsendita tra la Amplekso malsupre. Se iu el la subaj metodoj volas aldoni Span, ĝi prenas la nunan aktivan Span de la Amplekso, kreas novan Span kaj diras, ke ĝia gepatro estas la rezulta aktiva Span, kaj aktivas la novan Span. Kiam oni vokas eksterajn servojn, la nuna aktiva interspaco estas transdonita al ili, kaj tiuj servoj kreas novajn intervalojn rilate al ĉi tiu interspaco.
Ĉiuj laboroj trairas la Instancon Tracer, vi povas ricevi ĝin per la DI-mekanismo, aŭ GlobalTracer.get () kiel tutmonda variablo se la DI-mekanismo ne funkcias. Defaŭlte, se spurilo ne estis pravigita, NoopTracer revenos, kiu faras nenion.
Plue, la nuna amplekso estas akirita de la spurilo per la ScopeManager, nova amplekso estas kreita de la nuna kun ligado de la nova amplekso, kaj tiam la kreita Amplekso estas fermita, kiu fermas la kreitan amplekson kaj resendas la antaŭan Amplekso al. la aktiva stato. Amplekso estas ligita al fadeno, do dum plurfadena programado, vi ne devas forgesi transdoni la aktivan interspacon al alia fadeno, por plua aktivigo de la Amplekso de alia fadeno rilate al ĉi tiu interspaco.

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)) {
                ...
            }
        });
    }
}

Por plurfadena programado, ekzistas ankaŭ TracedExecutorService kaj similaj envolvaĵoj, kiuj aŭtomate plusendas la nunan interspacon al la fadeno kiam nesinkronaj taskoj estas lanĉitaj:

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

Por eksteraj http-petoj ekzistas TracingHttpClient

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

Problemoj, kiujn ni alfrontis

  • Faboj kaj DI ne ĉiam funkcias se la spurilo ne estas uzata en servo aŭ komponanto, do Aŭtomata kabligita Spurilo eble ne funkcias kaj vi devos uzi GlobalTracer.get().
  • Komentarioj ne funkcias se ĝi ne estas komponanto aŭ servo, aŭ se la metodo estas vokita de najbara metodo de la sama klaso. Vi devas atenti kontroli kio funkcias kaj uzi manan spurkreadon se @Traced ne funkcias. Vi ankaŭ povas kunligi plian kompililon por java komentarioj, tiam ili devus funkcii ĉie.
  • En la malnova printempa kaj printempa boto, la opentraing printempa nuba aŭtomata agordo ne funkcias pro cimoj en DI, tiam se vi volas, ke la spuroj en la printempaj komponantoj funkciu aŭtomate, vi povas fari ĝin analoge kun 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
  • Provu kun rimedoj ne funkcias en groovy, vi devas uzi try fine.
  • Ĉiu servo devas havi sian propran spring.application.name sub kiu spuroj estos registritaj. Kion faras apartan nomon por la vendo kaj la provo, por ne malhelpi ilin kune.
  • Se vi uzas GlobalTracer kaj tomcat, tiam ĉiuj servoj kurantaj en ĉi tiu tomcat havas unu GlobalTracer, do ili ĉiuj havos la saman servonomon.
  • Aldonante spurojn al metodo, vi devas esti certa, ke ĝi ne estas vokita multfoje en buklo. Necesas aldoni unu komunan spuron por ĉiuj vokoj, kiu garantias la tutan labortempon. Alie, troa ŝarĝo estos kreita.
  • Unufoje en jaeger-ui, tro grandaj petoj estis faritaj por granda nombro da spuroj, kaj ĉar ili ne atendis respondon, ili faris ĝin denove. Kiel rezulto, jaeger-query komencis manĝi multe da memoro kaj malrapidigi elastecon. Helpite per rekomenco de jaeger-query

Specimenado, konservado kaj rigardado de spuroj

Estas tri tipoj specimenaj spuroj:

  1. Const kiu sendas kaj konservas ĉiujn spurojn.
  2. Probabilista kiu filtras spurojn kun iu donita probableco.
  3. Rateliming kiu limigas la nombron da spuroj je sekundo. Vi povas agordi ĉi tiujn agordojn ĉe la kliento, ĉu ĉe la jaeger-agento aŭ ĉe la kolektanto. Nun ni uzas const 1 en la valuatora stako, ĉar ne estas tre multaj petoj, sed ili daŭras longan tempon. En la estonteco, se ĉi tio penos troan ŝarĝon sur la sistemo, vi povas limigi ĝin.

Se vi uzas Cassandra, tiam defaŭlte ĝi konservas nur spurojn dum du tagoj. Ni uzas elasta serĉado kaj spuroj estas konservitaj por ĉiam kaj ne estas forigitaj. Aparta indekso estas kreita por ĉiu tago, ekzemple jaeger-service-2019-03-04. Estonte, vi devas agordi aŭtomatan purigadon de malnovaj spuroj.

Por vidi la spurojn vi bezonas:

  • Elektu la servon, per kiu vi volas filtri spurojn, ekzemple tomcat7-default por servo, kiu funkcias en la tomcat kaj ne povas havi sian propran nomon.
  • Tiam elektu la operacion, la tempintervalon kaj la minimuman operaciotempon, ekzemple de 10 sekundoj, por preni nur longajn ekzekutojn.
    Service Tracing, OpenTracing kaj Jaeger
  • Iru al unu el la spuroj kaj vidu, kio malrapidiĝis tie.
    Service Tracing, OpenTracing kaj Jaeger

Ankaŭ, se iu peta id estas konata, tiam vi povas trovi spuron per ĉi tiu id tra etikedserĉo, se ĉi tiu id estas ensalutinta en la spuro.

Dokumentado

Artikoloj

Video

fonto: www.habr.com

Aldoni komenton