Service Tracing, OpenTracing ja Jaeger

Service Tracing, OpenTracing ja Jaeger

Käytämme projekteissamme mikropalveluarkkitehtuuria. Kun suorituskyvyn pullonkauloja ilmenee, paljon aikaa kuluu lokien seurantaan ja jäsentämiseen. Kun lokitiedostoon kirjataan yksittäisten toimintojen ajoituksia, on yleensä vaikea ymmärtää, mikä johti näiden toimintojen käynnistämiseen, seurata toimintojen järjestystä tai toiminnon aikasiirtymää suhteessa toiseen eri palveluissa.

Käsityön minimoimiseksi päätimme käyttää yhtä jäljitystyökaluista. Tässä artikkelissa käsitellään sitä, kuinka ja miksi voit käyttää jäljitystä ja miten teimme sen.

Mitä ongelmia voidaan ratkaista jäljityksellä

  1. Etsi suorituskyvyn pullonkaulat sekä yhdestä palvelusta että koko toteutuspuusta kaikkien osallistuvien palveluiden välillä. Esimerkiksi:
    • Useita lyhyitä peräkkäisiä puheluita palveluiden välillä, esimerkiksi geokoodaukseen tai tietokantaan.
    • Pitkät I/O-odotukset, kuten verkkosiirrot tai levyn lukemat.
    • Pitkä datan jäsennys.
    • Pitkät toiminnot vaativat suorittimen.
    • Koodiosat, joita ei tarvita lopullisen tuloksen saamiseksi ja jotka voidaan poistaa tai viivästyttää.
  2. Ymmärrä selvästi, missä järjestyksessä mitä kutsutaan ja mitä tapahtuu, kun toimenpide suoritetaan.
    Service Tracing, OpenTracing ja Jaeger
    Näkyy, että esim. Pyyntö tuli WS-palveluun -> WS-palvelu lisäsi dataa R-palvelun kautta -> lähetti sitten pyynnön V-palveluun -> V-palvelu latasi paljon dataa R:stä palvelu -> meni P-palveluun -> P-palvelu meni uudelleen palveluun R -> palvelu V jätti tuloksen huomioimatta ja meni palveluun J -> ja vasta sitten palautti vastauksen palveluun WS, jatkaen jonkin muun laskemista tausta.
    Ilman tällaista jälkiä tai yksityiskohtaista dokumentaatiota koko prosessille on erittäin vaikea ymmärtää, mitä tapahtuu, kun katsot koodia ensimmäistä kertaa, ja koodi on hajallaan eri palveluissa ja piilotettu laatikoiden ja rajapintojen taakse.
  3. Tietojen kerääminen suorituspuusta myöhempää lykättyä analyysiä varten. Jokaisessa suoritusvaiheessa voit lisätä tietoja jäljitykseen, joka on saatavilla tässä vaiheessa, ja sitten selvittää, mitkä syöttötiedot johtivat samanlaiseen skenaarioon. Esimerkiksi:
    • käyttäjätunnus
    • Oikeudet
    • Valitun menetelmän tyyppi
    • Loki- tai suoritusvirhe
  4. Jäljien muuttaminen mittareiden osajoukoksi ja jatkoanalyysi jo metriikan muodossa.

Mitä jälkiä voi kirjata. Span

Jäljittämisessä on käsite jänneväli, tämä on analogi yhdestä tukista konsoliin. Kylpylässä on:

  • Nimi, yleensä suoritetun menetelmän nimi
  • Palvelun nimi, jossa jakso luotiin
  • Oma yksilöllinen tunnus
  • Jonkinlainen metatieto avaimen/arvon muodossa, joka on kirjautunut siihen. Esimerkiksi menetelmän parametrit tai menetelmä päättyi virheeseen tai ei
  • Tämän ajanjakson alkamis- ja päättymisajat
  • Vanhemman span tunnus

Jokainen jänneväli lähetetään mittausalueen kerääjälle tallennettavaksi tietokantaan myöhempää tarkastelua varten heti, kun se on suorittanut suorituksensa. Jatkossa voit rakentaa puun kaikista jänteistä yhdistämällä vanhempien tunnuksella. Analysoitaessa voit löytää esimerkiksi jonkin palvelun kaikki jaksot, jotka kestivät kauemmin kuin jonkin aikaa. Lisäksi siirtymällä tiettyyn jänneväliin näet koko puun tämän jännevälin ylä- ja alapuolella.

Service Tracing, OpenTracing ja Jaeger

Opentrace, Jagger ja kuinka toteutimme sen projekteissamme

On olemassa yhteinen standardi opentrace, joka kuvaa miten ja mitä tulee kerätä ilman, että se on sidottu jäljittämällä tiettyyn toteutukseen millä tahansa kielellä. Esimerkiksi Javassa kaikki jälkityöt tehdään yleisen Opentrace API:n kautta ja sen alle voidaan piilottaa esimerkiksi Jaeger tai tyhjä oletustoteutus, joka ei tee mitään.
Meillä on käytössä Jääkäri Opentracen toteutuksena. Se koostuu useista komponenteista:

Service Tracing, OpenTracing ja Jaeger

  • Jaeger-agent on paikallinen agentti, joka asennetaan yleensä jokaiselle koneelle ja palvelut kirjataan siihen paikallisessa oletusportissa. Jos agenttia ei ole, kaikkien tämän koneen palvelujen jäljet ​​poistetaan yleensä käytöstä
  • Jaeger-collector - kaikki agentit lähettävät kerätyt jäljet ​​sille, ja se sijoittaa ne valittuun tietokantaan
  • Tietokanta on heidän suosikki cassandra, mutta käytämme elasticsearchia, parille muulle tietokannalle on toteutuksia ja muistissa oleva toteutus, joka ei tallenna mitään levylle
  • Jaeger-query on palvelu, joka menee tietokantaan ja palauttaa jo kerätyt jäljet ​​analysoitavaksi
  • Jaeger-ui on web-käyttöliittymä jälkien etsimiseen ja katseluun, se menee jaeger-kyselyyn

Service Tracing, OpenTracing ja Jaeger

Erillistä komponenttia voidaan kutsua tietyille kielille tarkoitetun opentrace jaegerin toteutukseksi, jonka kautta jänteet lähetetään jaeger-agentille.
Jaggerin yhdistäminen Javassa io.opentracing.Tracer-rajapinnan toteuttaminen, jonka jälkeen kaikki jäljet ​​sen kautta lentävät todelliselle agentille.

Service Tracing, OpenTracing ja Jaeger

Voit myös kytkeä jousikomponentin opentracing-kevät-pilvi-aloitus ja toteutus Jaegerilta opentracing-kevät-jaeger-pilvi-aloitus joka määrittää automaattisesti jäljityksen kaikelle, joka kulkee näiden komponenttien kautta, esimerkiksi http-pyynnöt ohjaimille, pyynnöt tietokantaan jdbc:n kautta jne.

Jälkien kirjaaminen Javassa

Jonnekin ylimmälle tasolle on luotava ensimmäinen Span, jonka voi tehdä automaattisesti esim. jousiohjaimella kun pyyntö vastaanotetaan, tai manuaalisesti, jos sellaista ei ole. Se lähetetään sitten alla olevan soveltamisalan kautta. Jos jokin alla olevasta menetelmästä haluaa lisätä alueen, se ottaa nykyisen ActiveSpanin laajuudesta, luo uuden alueen ja sanoo, että sen emo on tuloksena oleva activeSpan, ja tekee uuden alueen aktiiviseksi. Ulkopuolisiin palveluihin soitettaessa nykyinen aktiivinen jakso välitetään niille, ja kyseiset palvelut luovat uusia jaksoja tähän jaksoon viitaten.
Kaikki työ tapahtuu Tracer-instanssin kautta, voit saada sen DI-mekanismin kautta tai GlobalTracer.get () globaalina muuttujana, jos DI-mekanismi ei toimi. Oletusarvoisesti, jos Tracer ei ole alustettu, NoopTracer palauttaa, mikä ei tee mitään.
Lisäksi nykyinen skooppi saadaan jäljittimestä ScopeManagerin kautta, nykyisestä luodaan uusi, jossa on uuden alueen sidonta, ja sitten luotu Scope suljetaan, mikä sulkee luodun alueen ja palauttaa edellisen Scope aktiivinen tila. Scope on sidottu säikeeseen, joten monisäikeisessä ohjelmoinnissa sinun ei pidä unohtaa siirtää aktiivista jänneväliä toiseen säikeeseen, jotta toisen säikeen Scope aktivoidaan edelleen tämän jänteen suhteen.

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

Monisäikeiseen ohjelmointiin on olemassa myös TracedExecutorService ja vastaavat kääreet, jotka automaattisesti välittävät nykyisen jännevälin säikeeseen, kun asynkroniset tehtävät käynnistetään:

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

Ulkoisia http-pyyntöjä varten on TracingHttpClient

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

Kohtaamiamme ongelmia

  • Pavut ja DI eivät aina toimi, jos merkkiainetta ei käytetä palvelussa tai komponentissa Automaattinen langallinen Tracer ei ehkä toimi, ja sinun on käytettävä GlobalTracer.get().
  • Annotaatiot eivät toimi, jos se ei ole komponentti tai palvelu tai jos menetelmää kutsutaan saman luokan naapurimetodista. Sinun on oltava varovainen tarkistaaksesi, mikä toimii, ja käytä manuaalista jäljityksen luomista, jos @Traced ei toimi. Voit myös liittää ylimääräisen kääntäjän Java-merkintöjä varten, jolloin niiden pitäisi toimia kaikkialla.
  • Vanhassa jousi- ja jousikäynnistimessä opentraing spring cloud -automaattinen konfigurointi ei toimi DI:n bugien vuoksi, niin jos haluat jousikomponenttien jälkien toimivan automaattisesti, voit tehdä sen analogisesti 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
  • Kokeile resurssien kanssa ei toimi groovyssa, sinun on käytettävä kokeile vihdoin.
  • Jokaisella palvelulla on oltava oma spring.application.name, jonka alle jäljet ​​kirjataan. Mitä erillinen nimi myynnille ja testille tekee, jotta ne eivät häiritse niitä yhdessä.
  • Jos käytät GlobalTraceria ja tomcatia, kaikilla tässä tomcatissa suoritettavilla palveluilla on yksi GlobalTracer, joten niillä kaikilla on sama palvelun nimi.
  • Kun lisäät jälkiä menetelmään, sinun on varmistettava, että sitä ei kutsuta monta kertaa silmukassa. Kaikille puheluille on lisättävä yksi yhteinen jälki, joka takaa kokonaistyöajan. Muuten syntyy ylimääräistä kuormaa.
  • Kerran jaeger-ui:ssa tehtiin liian suuria pyyntöjä suurelle määrälle jälkiä, ja koska he eivät odottaneet vastausta, he tekivät sen uudelleen. Tämän seurauksena jaeger-kysely alkoi syödä paljon muistia ja hidastaa elastisuutta. Auttoi käynnistämällä jaeger-kyselyn uudelleen

Jälkien näytteenotto, varastointi ja katselu

Niitä on kolme tyyppiä näytteenoton jälkiä:

  1. Const, joka lähettää ja tallentaa kaikki jäljet.
  2. Todennäköisyys, joka suodattaa jäljet ​​tietyllä todennäköisyydellä.
  3. Ratelimiting, joka rajoittaa jälkien määrää sekunnissa. Voit määrittää nämä asetukset asiakkaalla, joko jaeger-agentilla tai keräilijällä. Nyt käytämme arvottajapinossa const 1:tä, koska pyyntöjä ei ole kovin paljon, mutta ne vievät kauan. Jos tämä kuormittaa järjestelmää tulevaisuudessa liikaa, voit rajoittaa sitä.

Jos käytät cassandraa, se tallentaa oletuksena vain jälkiä kahden päivän ajan. Meillä on käytössä elasticsearch ja jäljet ​​säilytetään koko ajan, eikä niitä poisteta. Jokaiselle päivälle luodaan oma hakemisto, esimerkiksi jaeger-palvelu-2019-03-04. Jatkossa sinun on määritettävä automaattinen vanhojen jälkien puhdistus.

Jotta voit tarkastella jälkiä, tarvitset:

  • Valitse palvelu, jolla haluat suodattaa jälkiä, esimerkiksi tomcat7-default palvelulle, joka on käynnissä tomcatissa ja jolla ei voi olla omaa nimeä.
  • Valitse sitten toiminto, aikaväli ja pienin toiminta-aika, esimerkiksi 10 sekunnista, jotta vain pitkiä suorituksia kestää.
    Service Tracing, OpenTracing ja Jaeger
  • Mene yhdelle jäljelle ja katso, mikä siellä hidastui.
    Service Tracing, OpenTracing ja Jaeger

Lisäksi, jos jokin pyyntötunnus on tiedossa, voit löytää jäljen tällä tunnuksella tunnistehaulla, jos tämä tunnus on kirjattu jäljitysväliin.

Asiakirjat

Artikkelit

video

Lähde: will.com

Lisää kommentti