使用Spring Boot、Micrometer和Zipkin进行分布式跟踪

希望做的事情

    • Spring Boot、Micrometer、RestTemplate を使用する

 

    • 複数アプリケーション間でトレースIDを伝播する

 

    トレース情報をZipkinに送信する

这篇文章是我参考的依据。

 

组成

distributed-tracing.drawio.png

创建一个 Spring Boot 应用程序

API服务的实现

创建一个与构成图的api-service相对应的应用程序。

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
	id("org.springframework.boot") version "3.2.0"
	id("io.spring.dependency-management") version "1.1.4"
	kotlin("jvm") version "1.9.20"
	kotlin("plugin.spring") version "1.9.20"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
	sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
	mavenCentral()
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("org.jetbrains.kotlin:kotlin-reflect")
	implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
	implementation("org.springframework.boot:spring-boot-starter-actuator")
	//	Micrometer Observation APIをOpenTelemetryにブリッジするライブラリ
	implementation("io.micrometer:micrometer-tracing-bridge-otel:1.2.0")
	// トレース情報を Zipkin に送信するライブラリ
	implementation("io.opentelemetry:opentelemetry-exporter-zipkin:1.32.0")
	testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<KotlinCompile> {
	kotlinOptions {
		freeCompilerArgs += "-Xjsr305=strict"
		jvmTarget = "17"
	}
}

tasks.withType<Test> {
	useJUnitPlatform()
}

要想在网络上自动传播跟踪,需要使用自动配置的RestTemplateBuilder。

import org.springframework.boot.autoconfigure.AutoConfigureAfter
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.client.RestTemplate

@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(HttpMessageConvertersAutoConfiguration::class)
class RestTemplateAutoConfiguration(
    private val restTemplateBuilder: RestTemplateBuilder
) {

    @Bean
    fun restTemplate(): RestTemplate {
        return restTemplateBuilder.build()
    }
}
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
import org.springframework.web.client.getForEntity
import org.springframework.web.util.UriComponentsBuilder

@Service
class CustomerService(
    private val restTemplate: RestTemplate
) {
    fun get(): CustomerRes {
        val uri = UriComponentsBuilder.fromUriString("http://localhost:8081")
            .path("customer")
            .toUriString()

        val response: ResponseEntity<CustomerRes> = restTemplate.getForEntity(
            uri,
            CustomerRes::class
        )

        return response.body!!
    }
}

data class CustomerRes(
    val value: String
)
import org.apache.commons.logging.LogFactory
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class CustomerController(
    private val customerService: CustomerService
) {
    private val logger = LogFactory.getLog(CustomerController::class.java)

    @RequestMapping("/customer")
    fun get(): HelloRes {
        logger.info("get() has been called")
        val result = customerService.get()
        return HelloRes(
            result.value
        )
    }

    class HelloRes(
        val value: String
    )
}
spring:
  application:
    name: api-service customer-service # Zipkin に送信されるサービス名。同一のサービスと認識されてしまう為、一意である必要がある

management:
  tracing:
    sampling:
      probability: 1.0 # トレース情報の送信割合。1.0 で全てのトレース情報が送信される

logging:
  level:
    root: INFO

顾客服务的执行

我会创建一个与构成图中的客户服务相对应的应用程序。
build.gradle.kts 文件与api-service相同。

import org.apache.commons.logging.LogFactory
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class CustomerController {
    private val logger = LogFactory.getLog(CustomerController::class.java)

    @GetMapping("/customer")
    fun get(): CustomerRes {
        logger.info("get() has been called")
        return CustomerRes("AAA株式会社")
    }

    class CustomerRes(
        val value: String
    )
}
spring:
  application:
    name: api-service customer-service # Zipkin に送信されるサービス名。同一のサービスと認識されてしまう為、一意である必要がある

management:
  tracing:
    sampling:
      probability: 1.0 # トレース情報の送信割合。1.0 で全てのトレース情報が送信される

logging:
  level:
    root: INFO

启动 Zipkin

docker run -d -p 9411:9411 openzipkin/zipkin

使用Zipkin查看跟踪信息

環境搭建完成后,我们将使用 Zipkin 查看实际的跟踪信息。
我们会多次运行应用程序。
http://localhost:8080/customer

访问 Zipkin。
http://localhost:9411/

Zipkin_list.png
Zipkin_detail.png
Zipkin_dependencies.png
广告
将在 10 秒后关闭
bannerAds