1. 분산추적이란?
분산 추적은 마이크로서비스 아키텍처와 같은 분산 시스템에서 요청의 전체 여정을 추적하고 모니터링하는 기술이다. 이 기술은 여러 서비스와 구성 요소를 거치는 요청의 경로를 시각화하고, 각 단계에서 소요된 시간과 발생한 오류를 식별한다. 분산 추적은 고유한 트레이스 ID를 사용하여 요청을 추적하며 각 작업 단위를 'Span'으로 표현한다. 이를 통해 개발자들은 성능 병목 현상을 파악하고, 오류의 근본 원인을 신속하게 찾아내며, 전체 시스템의 성능을 최적화할 수 있다. Zipkin과 같은 도구를 사용하면 이러한 분산 추적 데이터를 수집하고 시각화하여 효과적으로 분석할 수 있다.
2. 주요 개념
2 - 1. Trace
- trace는 하나의 요청이 시작부터 끝까지 각 서비스를 거치는 전체 흐름을 나타낸다.
- 하나의 trace는 여러 개의 span으로 구성된다.
- 분산 시스템에서 클라이언트의 요청이 여러 서비스로 전달될 때, 각 서비스 호출이 trace의 일부로 기록된다.
- trace ID는 각 span에 공통으로 부여되며, 이를 통해 전체 요청 흐름을 추적할 수 있다.
2 - 2 Span
- span은 분산 추적에서 가장 작은 단위로, 특정 서비스 내에서의 개별 작업 또는 요청을 나타낸다.
- 각 span은 시작 시간과 종료 시간을 기록하여 작업의 지속 시간을 나타낸다.
- span은 고유한 span ID를 가지며, 이는 trace ID와 함께 특정 작업을 식별하는 데 사용된다.
- span은 부모-자식 관계를 가질 수 있으며, 이를 통해 호출 계층 구조를 표현한다.
- span에는 메타데이터(태그, 로그, 이벤트 등)를 추가하여 상세한 정보를 기록할 수 있다.
2 - 3 Context
- context는 요청이 서비스 간에 전달될 때 함께 전파되어, 각 서비스는 요청의 전체 흐름에 대한 정보를 가질 수 있게 된다.
- context는 trace ID, span ID, 부모 span ID 등의 정보를 포함하여 각 서비스가 요청의 출처와 경로를 추적할 수 있도록 돕는다.
- 서비스 호출 간에 context를 유지함으로써, 분산 시스템 전체에서 일관된 추적이 가능해진다.
3. 분산 추적이 필요한 이유
3 - 1. 시스템 가시성 향상
여러 서비스에 걸친 요청의 전체 흐름을 시각화하여 시스템의 작동 방식을 더 잘 이해할 수 있게 해준다.
3 - 2. 문제 해결 시간 단축
오류나 성능 저하의 원인을 신속하게 파악하고 해결할 수 있어 평균 탐지 시간(MTTD)과 평균 해결 시간(MTTR)을 줄일 수 있다.
3 - 3. 성능 최적화
병목 현상과 비효율적인 코드를 식별하여 시스템 성능을 개선할 수 있다.
3 - 4. 서비스간 관계 이해
복잡한 마이크로서비스 환경에서 서비스 간의 상호작용과 의존성을 명확히 파악할 수 있다.
3 - 5. 협업 개선
여러 팀이 관리하는 서비스들 사이에서 문제 발생시 책임 소재를 명확히 하고 협업을 촉진한다.
4. Zipkin이란?
Zipkin은 분산 추적 시스템으로, 마이크로서비스 아키텍처에서 요청의 흐름을 추적하고 시각화하는 데 사용되는 오픈 소스 도구이다.
4 - 1. 주요 특징
4 - 1 - 1. trace 수집 및 저장
Zipkin은 분산 시스템에서 발생하는 trace를 수집하고 저장한다.
4 - 1 - 2. trace 시각화
웹 기반 UI를 통해 수집된 trace를 시각화한다. 이를 통해 요청의 전체 흐름을 그래픽으로 확인하고, 각 서비스간의 호출 관계를 분석할 수 있다.
4 - 1 - 3. 성능 분석
각 span의 시작 시간과 종료 시간을 기록하여, 서비스 간의 지연 시간이나 성능 병목을 식별하는 데 도움을 준다.
4 - 1 - 4. 오류 추적
요청 처리 중 발생하는 오류를 추적하고, 오류가 발생한 위치를 정확히 실벽할 수 있어 문제 해결과 디버깅이 용이해진다.
4 - 1 - 5. 쿼리 및 필터링
trace 데이터를 쿼리하고 필터링할 수 있는 기능을 제공한다.
5. Zipkin 실습
Eureka Server, Order-Service, Product-Service 1대식을 띄운다.
order를 호출할 때 product의 정보를 가져오는 상황이다.
API 호출 후 Zipkin을 통해 분산 추적이 잘 되었는지 확인한다.
5 - 1. Zipkin 서버 실행
docker run -d -p 9411:9411 openzipkin/zipkin
localhost:9411/zipkin/
5 - 2. product-service
5 - 2 - 1. build.gradle(product)
dependencies {
// zipkin을 포함한 분산 추적 시스템 디펜던시
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-tracing-bridge-brave'
implementation 'io.github.openfeign:feign-micrometer'
implementation 'io.zipkin.reporter2:zipkin-reporter-brave'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
Zipkin을 사용하려면 Micrometer 의존성이 필요하다.
Micrometer는 Spring 기반 애플리케이션에서 메트릭을 수집하고 모니터링하기 위한 라이브러리이다.
5 - 2 - 2. application.yml(product)
spring:
application:
name: product-service
server:
port: 19092
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
management:
zipkin:
tracing:
endpoint: "http://localhost:9411/api/v2/spans" # zipkin에서 정해준 엔드포인트
tracing:
sampling:
probability: 1.0 # 1.0은 전체
윗 부분은 eureka-client 설정이고, 아래가 zipkin 설정이다.
Zipkin 서버가 로컬 환경에서 기본 포트(9411)로 실행 중이며, 추적 데이터를 받아들이는 API 엔드포인트를 나타내고 있다.
`probability: 1.0` 은 추적 데이터의 샘플링 비율을 설정하는 것이다.
1.0은 모든 요청(100%)에 대해 추적 데이터를 수집한다는 의미다.
이 값을 낮추면(예: 0.1) 전체 요청의 일부(10%)만 추적하게 되어 성능 부하를 줄일 수 있다.
프로덕션 환경에서는 트래픽 양에 따라 이 값을 조정하는 것이 일반적이다.
5 - 3. order-service
5 - 3 - 1. build.gradle(order)
dependencies {
// zipkin을 포함한 분산 추적 시스템 디펜던시
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-tracing-bridge-brave'
implementation 'io.github.openfeign:feign-micrometer'
implementation 'io.zipkin.reporter2:zipkin-reporter-brave'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
product-service와 동일하다.
5 - 3 - 2. application.yml(order)
서버 포트만 19091이고, 나머지는 product와 동일하다.
6. Run
localhost:19091/order/1
API 호출 후 Zipkin 웹 UI 확인
Spans 값이 3인 것의 `SHOW` 버튼을 클릭한다.
order-service가 product-service를 호출하고 있음을 알 수 있다.
시간이 얼마나 걸렸는지도 확인 가능하다.
Dependencies 탭
order-service 와 product-service의 관계를 볼 수 있다.
References
https://java-online-training.de/?p=59
https://easywritten.com/post/using-spring-boot-3-with-zipkin/
https://stackademic.com/blog/adding-micrometer-tracing-to-spring-boot-3-with-brave-zipkin
https://openobserve.ai/resources/distributed-tracing-basics-understanding
'MSA' 카테고리의 다른 글
2024 11 28 TIL - Spring Cloud Config (1) | 2024.11.28 |
---|---|
2024 11 27 TIL - API Gateway, Spring Cloud Gateway (0) | 2024.11.27 |
2024 11 26 TIL - CircuitBreaker(Resilience4j) (0) | 2024.11.26 |
2024 11 25 TIL - 로드 밸런싱, Netflix Ribbon (0) | 2024.11.25 |
2024 11 22 TIL - Spring Cloud Netfilx Eureka로 알아보는 서비스 디스커버리 (3) | 2024.11.22 |