Service Tracing, OpenTracing og Jaeger

Service Tracing, OpenTracing og Jaeger

Vi bruker mikrotjenestearkitektur i våre prosjekter. Når ytelsesflaskehalser oppstår, brukes mye tid på å overvåke og analysere logger. Når du logger tidspunktene for individuelle operasjoner til en loggfil, er det vanligvis vanskelig å forstå hva som førte til påkallingen av disse operasjonene, å spore handlingssekvensen eller tidsforskyvningen til en operasjon i forhold til en annen i forskjellige tjenester.

For å minimere manuelt arbeid bestemte vi oss for å bruke et av sporingsverktøyene. Om hvordan og hvorfor du kan bruke sporing og hvordan vi gjorde det, og vil bli diskutert i denne artikkelen.

Hvilke problemer kan løses med sporing

  1. Finn ytelsesflaskehalser både innenfor en enkelt tjeneste og i hele utførelsestreet mellom alle deltakende tjenester. For eksempel:
    • Mange korte påfølgende samtaler mellom tjenester, for eksempel til geokoding eller til en database.
    • Lange I/O-ventinger, for eksempel nettverksoverføringer eller diskavlesninger.
    • Lang dataparsing.
    • Lange operasjoner som krever cpu.
    • Kodedeler som ikke er nødvendige for å få det endelige resultatet og kan fjernes eller forsinkes.
  2. Forstå tydelig i hvilken rekkefølge hva som kalles og hva som skjer når operasjonen utføres.
    Service Tracing, OpenTracing og Jaeger
    Det kan ses at for eksempel forespørselen kom til WS-tjenesten -> WS-tjenesten supplerte dataene gjennom R-tjenesten -> sendte deretter en forespørsel til V-tjenesten -> V-tjenesten lastet inn mye data fra R-tjeneste -> gikk til P-tjenesten -> P-tjenesten gikk igjen til tjeneste R -> tjeneste V ignorerte resultatet og gikk til tjeneste J -> og returnerte først da svaret til tjeneste WS, mens han fortsatte å beregne noe annet i bakgrunnen.
    Uten et slikt spor eller detaljert dokumentasjon for hele prosessen, er det svært vanskelig å forstå hva som skjer når man ser på koden for første gang, og koden er spredt over ulike tjenester og gjemt bak en haug med binger og grensesnitt.
  3. Innsamling av informasjon om utførelsestreet for påfølgende utsatt analyse. På hvert trinn av utførelse kan du legge til informasjon til sporet som er tilgjengelig på dette stadiet, og deretter finne ut hvilke inndata som førte til et lignende scenario. For eksempel:
    • bruker-ID
    • Rettigheter
    • Type valgt metode
    • Logg eller utførelsesfeil
  4. Gjøre spor til en delmengde av metrikker og videre analyse allerede i form av metrikker.

Hvilket spor kan logge. Spenn

I sporing er det konseptet med et spenn, dette er en analog av en logg, til konsollen. Spaet har:

  • Navn, vanligvis navnet på metoden som ble utført
  • Navnet på tjenesten der spennet ble generert
  • Egen unik ID
  • En slags metainformasjon i form av en nøkkel/verdi som er logget inn i den. For eksempel, metodeparametere eller metoden endte med en feil eller ikke
  • Start- og sluttider for dette spennet
  • ID for overordnet span

Hvert span sendes til span-samleren for å bli lagret i databasen for senere gjennomgang så snart det har fullført sin utførelse. I fremtiden kan du bygge et tre med alle spenn ved å koble til med foreldre-ID. Når du analyserer, kan du for eksempel finne alle spennene i en tjeneste som tok mer enn litt tid. Videre, ved å gå til et spesifikt spenn, se hele treet over og under dette spennet.

Service Tracing, OpenTracing og Jaeger

Opentrace, Jagger og hvordan vi implementerte det for våre prosjekter

Det er en felles standard opentrace, som beskriver hvordan og hva som skal samles inn, uten å være knyttet til en spesifikk implementering på noe språk. For eksempel i Java utføres alt arbeid med spor gjennom det vanlige Opentrace API, og under det kan for eksempel Jaeger eller en tom standardimplementering som ikke gjør noe skjules.
Vi bruker Jaeger som en implementering av Opentrace. Den består av flere komponenter:

Service Tracing, OpenTracing og Jaeger

  • Jaeger-agent er en lokal agent som vanligvis er installert på hver maskin og tjenester er logget på den på den lokale standardporten. Hvis det ikke er noen agent, er spor av alle tjenester på denne maskinen vanligvis deaktivert
  • Jaeger-collector - alle agenter sender innsamlede spor til den, og den plasserer dem i den valgte databasen
  • Databasen er deres foretrukne cassandra, men vi bruker elasticsearch, det er implementeringer for et par andre databaser og en in-memory implementering som ikke lagrer noe på disk
  • Jaeger-query er en tjeneste som går til databasen og returnerer allerede innsamlede spor for analyse
  • Jaeger-ui er et nettgrensesnitt for søk og visning av spor, det går til jaeger-query

Service Tracing, OpenTracing og Jaeger

En egen komponent kan kalles implementeringen av opentrace jaeger for spesifikke språk, gjennom hvilke spenn sendes til jaeger-agent.
Koble til Jagger i Java kommer ned til å implementere io.opentracing.Tracer-grensesnittet, hvoretter alle spor gjennom det vil fly til den virkelige agenten.

Service Tracing, OpenTracing og Jaeger

Også for fjærkomponenten kan du koble til opentracing-fjær-sky-starter og implementering fra Jaeger opentracing-spring-jaeger-cloud-starter som automatisk vil konfigurere sporing for alt som går gjennom disse komponentene, for eksempel http-forespørsler til kontrollere, forespørsler til databasen gjennom jdbc, etc.

Sporer logging i Java

Et sted på toppnivået må det første spennet opprettes, dette kan gjøres automatisk, for eksempel av fjærkontrolleren når en forespørsel mottas, eller manuelt hvis det ikke er noen. Den overføres deretter gjennom Scope nedenfor. Hvis noen av metodene nedenfor ønsker å legge til et spenn, tar det gjeldende activeSpan fra omfanget, oppretter et nytt spenn og sier at dets overordnede er det resulterende activeSpan, og gjør det nye spennet aktivt. Når du ringer eksterne tjenester, sendes det gjeldende aktive spennet til dem, og disse tjenestene oppretter nye spenn med referanse til dette spennet.
Alt arbeid går gjennom Tracer-forekomsten, du kan få det gjennom DI-mekanismen, eller GlobalTracer.get () som en global variabel hvis DI-mekanismen ikke fungerer. Som standard, hvis tracer ikke er initialisert, vil NoopTracer returnere som ikke gjør noe.
Videre hentes det gjeldende omfanget fra sporeren gjennom ScopeManager, et nytt omfang opprettes fra det nåværende med en binding av det nye området, og deretter lukkes det opprettede omfanget, som lukker det opprettede området og returnerer det forrige omfanget til den aktive tilstanden. Omfanget er knyttet til en tråd, så ved flertrådsprogrammering må du ikke glemme å overføre det aktive spennet til en annen tråd, for videre aktivering av omfanget til en annen tråd med referanse til dette spennet.

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

For flertrådsprogrammering er det også TracedExecutorService og lignende wrappers som automatisk videresender gjeldende spenn til tråden når asynkrone oppgaver startes:

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

For eksterne http-forespørsler er det TracingHttpClient

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

Problemer vi møtte

  • Bønner og DI fungerer ikke alltid hvis traceren ikke brukes i en tjeneste eller komponent, da Autokablet Tracer fungerer kanskje ikke, og du må bruke GlobalTracer.get().
  • Merknader fungerer ikke hvis det ikke er en komponent eller tjeneste, eller hvis metoden kalles fra en tilstøtende metode av samme klasse. Du må være forsiktig med å sjekke hva som fungerer og bruke manuell sporoppretting hvis @Traced ikke fungerer. Du kan også legge ved en ekstra kompilator for java-kommentarer, da bør de fungere overalt.
  • I den gamle fjær- og fjærstøvelen fungerer ikke opentraing fjærsky-autokonfigurasjonen på grunn av feil i DI, så hvis du vil at sporene i fjærkomponentene skal fungere automatisk, kan du gjøre det analogt med 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
  • Prøv med ressurser fungerer ikke i groovy, du må bruke prøve til slutt.
  • Hver tjeneste må ha sitt eget spring.application.name som sporene skal logges under. Hva betyr et eget navn for salget og testen, for ikke å forstyrre dem sammen.
  • Hvis du bruker GlobalTracer og tomcat, har alle tjenester som kjører i denne tomcat én GlobalTracer, så de vil alle ha samme tjenestenavn.
  • Når du legger til spor til en metode, må du være sikker på at den ikke kalles mange ganger i en løkke. Det er nødvendig å legge til ett felles spor for alle samtaler, som garanterer den totale arbeidstiden. Ellers vil det bli opprettet en overbelastning.
  • En gang i jaeger-ui ble det gjort for store forespørsler om et stort antall spor, og siden de ikke ventet på svar, gjorde de det igjen. Som et resultat begynte jaeger-query å spise mye minne og senke elastikken. Hjelpet ved å starte jaeger-query på nytt

Prøvetaking, lagring og visning av spor

Det er tre typer prøvetakingsspor:

  1. Const som sender og lagrer alle spor.
  2. Probabilistisk som filtrerer spor med en viss gitt sannsynlighet.
  3. Ratelimiting som begrenser antall spor per sekund. Du kan konfigurere disse innstillingene på klienten, enten på jaeger-agenten eller på samleren. Nå bruker vi const 1 i valuator-stabelen, siden det ikke er veldig mange forespørsler, men de tar lang tid. I fremtiden, hvis dette vil utøve en overdreven belastning på systemet, kan du begrense det.

Hvis du bruker cassandra, lagrer den som standard bare spor i to dager. Vi bruker elasticsearch og spor lagres for alltid og slettes ikke. Det opprettes en egen indeks for hver dag, for eksempel jaeger-service-2019-03-04. I fremtiden må du konfigurere automatisk rengjøring av gamle spor.

For å se sporene trenger du:

  • Velg tjenesten du vil filtrere spor etter, for eksempel tomcat7-standard for en tjeneste som kjører i tomcat og ikke kan ha sitt eget navn.
  • Velg deretter operasjonen, tidsintervallet og minimum operasjonstid, for eksempel fra 10 sekunder, for å ta bare lange utførelser.
    Service Tracing, OpenTracing og Jaeger
  • Gå til et av sporene og se hva som bremset der.
    Service Tracing, OpenTracing og Jaeger

Dessuten, hvis en forespørsels-ID er kjent, kan du finne et spor etter denne ID-en gjennom et tag-søk, hvis denne IDen er logget i sporingsområdet.

Документация

Artikler

Video

Kilde: www.habr.com

Legg til en kommentar