使用Spring Boot、Micrometer和Zipkin进行分布式跟踪
希望做的事情
- 
- Spring Boot、Micrometer、RestTemplate を使用する
 
 
- 
- 複数アプリケーション間でトレースIDを伝播する
 
 
- トレース情報をZipkinに送信する
 
这篇文章是我参考的依据。
组成

创建一个 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/


