Jaeger integráció tavaszi rendszerindító alkalmazással

(Himank Batra) (szeptember 9.) , 2020)

Jaeger integráció tavaszi rendszerindító alkalmazással

Először értsük meg, mi a Jaeger

A Jaeger nyílt forráskódú szoftver tranzakciók nyomon követésére az elosztott szolgáltatások között.

Komplex mikroszolgáltatási környezetek megfigyelésére és hibaelhárítására használják.

Az Uber telekommunikációs vállalat 2015-ben nyílt forráskódú projektként fejlesztette ki a Jaegert. Felhőként fogadták el. A Native Computing Foundation (CNCF) inkubációs projektje 2017-ben, majd 2019-ben fokozatosan lépett át.

Mi az elosztott nyomkövetés?

Az elosztott nyomkövetés segítségével megtekintheti és megértheti Az események teljes láncolata a mikroszolgáltatások közötti komplex interakcióban.

A modern, felhőalapú szoftverfejlesztés a mikroszolgáltatásokra támaszkodik: független szolgáltatások, amelyek mindegyike más-más alapfunkciót nyújt. Amikor egy felhasználó kérelmet nyújt be egy alkalmazásban, sok egyedi szolgáltatás reagál eredményre.

Egy alkalmazásban egyetlen hívás több tucat különböző szolgáltatást hívhat meg, amelyek kölcsönhatásba lépnek egymással. Hogyan tudják a fejlesztők és mérnökök elkülöníteni a problémát, ha valami nem stimmel, vagy ha a kérés lassan fut? Szükségünk van egy módra az összes kapcsolat nyomon követésére.

Itt jön létre az elosztott nyomkövetés. Gyakran egy szervizhálózat részeként fut, ami a mikroszolgáltatások kezelésének és megfigyelésének módja.

Jaeger elosztott nyomkövetéssel követi a kérés útvonalát különböző mikroszolgáltatásokon keresztül. A találgatás helyett vizuális ábrázolást láthatunk a hívási folyamatokról.

A tranzakciókról szervezett információk hasznosak a hibakeresésben és az optimalizálásban. A Jaeger tartalmaz eszközöket az elosztott tranzakciók nyomon követésére, a teljesítmény és a késleltetés optimalizálására, valamint a kiváltó okok elemzésére (RCA), a problémamegoldás egyik módszerére.

Jaeger terminológia és komponensek

Jaeger a végrehajtási kérelmeket nyomok ként mutatja be. A nyomkövetés az adatok / végrehajtás útvonalát mutatja a rendszeren keresztül.

A nyomkövetés egy vagy több tartományból áll. A span egy logikus munkaegység Jaegerben. Minden szakasz tartalmazza a művelet nevét, kezdési idejét és időtartamát. A szakaszok egymásba ágyazhatók és megrendelhetők.

A Jaeger számos összetevőt tartalmaz, amelyek együttesen gyűjtik, tárolják és vizualizálják a szakaszokat és nyomokat.

Jaeger Client nyelveket tartalmaz az OpenTracing API specifikus megvalósításai az elosztott nyomkövetéshez. Ezeket manuálisan vagy különféle nyílt forráskódú keretrendszerekkel lehet használni.

Jaeger Agent egy hálózati démon, amely a User Datagram Protocol-on keresztül küldött tartományokat figyeli. Az ügynököt ugyanarra a gazdagépre kell helyezni, mint a műszeres alkalmazást. Ezt általában egy oldalkocsin keresztül valósítják meg olyan konténerkörnyezetekben, mint a Kubernetes.

Jaeger Collector fogadja a szakaszokat, és feldolgozási sorba helyezi őket.

A gyűjtőknek egy állandó tároló háttérrendszer, így Jaeger rendelkezik egy plug-in mechanizmussal a storage.

Query olyan szolgáltatásra, amely lekéri a nyomokat a tárolóból.

Jaeger Console egy felhasználói felület, amely lehetővé teszi az elosztott nyomkövetési adatok megjelenítését.

Miért éppen Jaeger?

Amint a földi mikroszolgáltatást végző szakemberek gyorsan rájönnek, az elosztott architektúrára való áttéréskor felmerülő operatív problémák többsége végül két területen alapszik: hálózatépítés és megfigyelhetőség. Egyszerűen nagyságrendekkel nagyobb probléma az összefonódó elosztott szolgáltatások halmazának hálózata és hibakeresése egyetlen monolitikus alkalmazással szemben.

Jaeger műveletben

Integráljuk a jaeger programot egy tavaszi rendszerindító alkalmazásba.

Először állítsuk be gyorsan a tavaszi rendszerindító alkalmazásokat.

Az ötlet itt neveket generál úgy, hogy híres tudós neveket állít össze állatnevekkel.

Tehát 3 mikroszolgáltatást fogunk építeni a tavaszi csomagtartóval, azaz animal-name-service , név-generátor-szolgáltatás, és tudós-név- szolgáltatás >>/em>.

Ügyfélkérelem tudós és állat összefűzött névre a név-generátor-szolgáltatásból amely belsőleg hívja az animal-name-service és a scientist-name-service.

Ugyanezt mutatja az alábbi ábra.

Mikroszolgáltatási példa

Építsük meg gyorsan három mikroszolgáltatásunkat a rugós inicializálás r használatával.

Hozzáadjuk a spring-boot-starter-web függőséget, miközben a tavaszi boot alkalmazásokat generáljuk.

Most 3 tavaszi boot alkalmazás készen áll. Vegyük fel ezt a 3 mikroszolgáltatást egy opentracing-microservices-example.

mappába, és importáljuk ezt a mappát a kedvenc szerkesztőjébe. Az IntelliJ szót használom.

Mivel az animal-name-service és scientist- név-szolgáltatás a name-generator-service.

ügyfelet színleljük ehhez. Tehát tegyük fel a spring-cloud-starter-openfeign: 2.2.3.RELEASE függőséget a name-generator-service.

Itt található a mind a 3 mikroszolgáltatás.

AnimalNameService :

package com.example.ans;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.core.io.ClassPathResource;import org.springframework.http.HttpHeaders;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestHeader;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.List;import java.util.Random;import java.util.stream.Collectors;@SpringBootApplication
public class AnimalNameService {public static void main(String[] args) {SpringApplication.run(AnimalNameService.class, args);}}@RestController
@RequestMapping("/api/v1/animals")
class AnimalNameResource {private final List animalNames;private Random random;public AnimalNameResource() throws IOException {InputStream inputStream = new ClassPathResource("/animals.txt").getInputStream();try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {animalNames = reader.lines().collect(Collectors.toList());}random = new Random();}@GetMapping(path = "/random")
public String name(@RequestHeader HttpHeaders headers) {String name = animalNames.get(random.nextInt(animalNames.size()));return name;}}

application.properties:

server.port=9000

NameGeneratorService:

Itt a következőt használom: com.shekhargulati: strman: 0.4 .0 könyvtár az állat- és tudósnév kebab-esetké konvertálásához.

package com.example.ngs;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import static strman.Strman.toKebabCase;@SpringBootApplication
@EnableFeignClients
public class NameGeneratorService {public static void main(String[] args) {SpringApplication.run(NameGeneratorService.class, args);}}@FeignClient(name = "scientist-service-client", url = "${scientist.service.prefix.url}")
interface ScientistServiceClient {@GetMapping("/api/v1/scientists/random")
String randomScientistName();}@FeignClient(name = "animal-service-client", url = "${animal.service.prefix.url}")
interface AnimalServiceClient {@GetMapping("/api/v1/animals/random")
String randomAnimalName();}@RestController
@RequestMapping("/api/v1/names")
class NameResource {@Autowired
private AnimalServiceClient animalServiceClient;@Autowired
private ScientistServiceClient scientistServiceClient;@GetMapping(path = "/random")
public String name() throws Exception {String animal = animalServiceClient.randomAnimalName();String scientist = scientistServiceClient.randomScientistName();String name = toKebabCase(scientist) + "-" + toKebabCase(animal);return name;}}

application.properties:

server.port=8080scientist.service.prefix.url=http://localhost:8090animal.service.prefix.url=http://localhost:9000

ScientistNameService:

package com.example.sns;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.core.io.ClassPathResource;import org.springframework.http.HttpHeaders;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestHeader;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.List;import java.util.Random;import java.util.stream.Collectors;@SpringBootApplication
public class ScientistNameService {public static void main(String[] args) {SpringApplication.run(ScientistNameService.class, args);}}@RestController
@RequestMapping("/api/v1/scientists")
class ScientistNameResource {private final List scientistsNames;private Random random;public ScientistNameResource() throws IOException {InputStream inputStream = new ClassPathResource("/scientists.txt").getInputStream();try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {scientistsNames = reader.lines().collect(Collectors.toList());}random = new Random();}@GetMapping(path = "/random")
public String name(@RequestHeader HttpHeaders headers) {String name = scientistsNames.get(random.nextInt(scientistsNames.size()));return name;}}

application.properties :

server.port=8090

Most mind a 3 alkalmazást futtatjuk, és a http: // localhost: 8080 / api / v1 / names webhelyre megyünk / random böngészőben.

Kapunk néhány véletlenszerű nevet: john-cockcroft-snapping-turtle

Tehát most az alkalmazásunk a beállítás elkészült.

Most integráljuk a jaegert ezekbe az alkalmazásokba, hogy nyomon tudjuk követni minden egyes kérést.

Csak hozzá kell adnunk az alábbi függőséget mindhárom pom.xml-hez.


io.opentracing.contrib
opentracing-spring-jaeger-cloud-starter3.1.2

És az alábbi tulajdonságokat hozzá kell adnunk az application.properties fájlhoz mindhárom alkalmazáshoz.

spring.application.name= // example : name-generator-service (this will be displayed in jaeger for respective service)opentracing.jaeger.udp-sender.host=localhost //udp host for sender. By default Jaeger libraries use a UDP sender to report finished spans to the jaeger-agent daemonopentracing.jaeger.udp-sender.port=6831 // udp portopentracing.jaeger.log-spans=true // logs the spans in console

Futtassa a Jaeger-t a dokkolóban az alábbi paranccsal:

docker run -p 9090:16686 — name jaeger -d jaegertracing/all-in-one:1.17

Most indítsa újra az alkalmazást. És keresse meg a localhost: 9090 böngészőt. Kapunk egy jaeger kezdőlapot.

Továbbá keresse fel a böngészőben a http: // localhost: 8080 / api / v1 / names / random oldalt. Ehhez hasonlóan kapsz néhány véletlenszerű nevet.

De most nyomon tudjuk követni a kérést. Jelentkezzen be a jaeger műszerfalon, válassza a név- generátor-szolgáltatás.

szolgáltatást, majd kattintson a nyomkövetés keresésére. nyomokat kapunk, amint az az alábbi képen látható a név-generátor-szolgáltatás számára.

Jaeger névgenerátor szolgáltatás

Világosan láthatjuk, hogy 5 fesztáv van, amikor ezt elmélyítjük.

név-generátor-szolgáltatás (1 fesztáv)

név-generátor-szolgáltatás-> állat-név-szolgáltatás (2 fesztávolság)

név-generátor-szolgáltatás-> tudós- név-szolgáltatás (2 fesztávolság)

Ez az alábbi képen látható.

Jaeger névgenerátor szolgáltatás nyomkövetése

Itt mindent automatikusan konfigurál az opentracing-spring-jaeger-cloud-starter könyvtár, amelynek TracingAspect nevű osztálya alapvetően varázsol.

@Aspect
class TracingAspect {
TracingAspect() {
}

@Around("execution (* feign.Client.*(..)) && !within(is(FinalType))")
public Object feignClientWasCalled(ProceedingJoinPoint pjp) throws Throwable {
Object bean = pjp.getTarget();
if (!(bean instanceof TracingClient)) {
Object[] args = pjp.getArgs();
return (new TracingClientBuilder((Client)bean, FeignTracingAutoConfiguration.this.tracer)).withFeignSpanDecorators(FeignTracingAutoConfiguration.this.spanDecorators).build().execute((Request)args[0], (Options)args[1]);
} else {
return pjp.proceed();
}
}
}

Hozzáadtam a Dockerfile fájlt, a docker-compose és a docker- setup.sh az alkalmazás futtatásának megkönnyítése érdekében. fizetési kódot, és futtassa közvetlenül a docker-setup.sh fájlt.

A kódot a Github adattáramban találhatja meg. link .

Ezt ihlette Shekhar Gulati blogja .

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük