[MSA] Zipkin을 활용한 분산 로그 추적

나르·2022년 2월 16일
0

Architecture

목록 보기
6/6
post-thumbnail

MSA와 OpenTracing

MSA 환경에서는 하나의 요청에 대해 도메인별로 분리된 여러 대의 서버가 통신하며 요청을 처리하게 됩니다. 때문에 처리 도중 문제가 발생하게 되면, 어느 지점이 문제인지 빠르게 찾아낼 수 있어야 합니다.

모놀리식 환경에서도 비동기 호출이나 멀티 스레드 작업에 대해 히스토리를 추적해야 하는 상황이라면, OpenTracing을 통해 좀 더 편리한 로깅 환경을 제공 받을 수 있습니다.

OpenTracing은 애플리케이션 간 분산 추적을 위한 표준이라고 할 수 있고, 대표적인 구현체로는 Jaeger와 Zipkin이 있습니다.

Zipkin

Zipkin은 분산 환경에서 로그 트레이싱하는 오픈소스로 트위터에서 개발되었으며, 현재 가장 활성화된 오픈소스입니다. Zipkin으로 추적할 수 있는 분산 트랜잭션은 HTTP, gRPC가 있습니다.

Sleuth를 통해 생성된 Trace 정보를 Zipkin으로 송부하면 트래픽의 흐름을 시각화하여 보여줍니다.

  • Zipkin client library: 서비스에서 트레이스 정보를 수집하여 Zipkin Server의 Collector 모듈로 전송하며, 지원하는 언어는 Java, Javascript, Go, C# 등이 있습니다. Collector로 전송할 때는 다양한 프로토콜을 사용할 수 있지만 일반적으로 HTTP를 사용하고, 시스템이 클 경우 Kafka 큐를 통해서도 전송을 합니다.
  • Collector: Zipkin Client Library로부터 전달된 트레이스 정보 유효성을 검증하고 검색 가능하게 저장 및 색인화 합니다.
  • Storge: Zipkin Collector로 보내진 트레이스 정보는 Storage에 저장됩니다. Zipkin은 초창기에는 Cassandra에 데이터를 저장하도록 만들어졌지만(Cassandra가 확장 가능하고 유연한 스키마를 가지고 있기 때문에 Twitter 내에서 많이 사용되었음), 그 뒤로 ElasticSearch나 MySQL도 지원 가능하게 구성되었습니다. 그 외에 In-Memory도 지원 가능하기 때문에 간단히 로컬에서 테스트할 때는 In-Memory, 소규모는 MySQL, 운영환경에 적용은 Cassandra나 ElasticSearch를 저장소로 사용하는 것이 좋습니다.
  • API(Query Service): 저장되고 색인화된 트레이스 정보를 검색하기 위한 JSON API이며, 주로 Web UI에서 호출됩니다.
  • Web UI: 수집된 트레이스 정보를 확인할 수 있는 GUI로 만들어진 대쉬보드이며, 서비스 / 시간 / 어노테이션 기반으로 데이터 확인이 가능합니다. Zipkin 서버의 대쉬보드를 사용할 수도 있고, ElasticSearch 백앤드를 이용한 경우는 Kibana 활용도 가능합니다.

Spring Cloud Sleuth

Spring Cloud Sleuth is able to trace your requests and messages so that you can correlate that communication to corresponding log entries. You can also export the tracing information to an external system to visualize latency. Spring Cloud Sleuth supports OpenZipkin compatible systems directly.

Slueth는 스프링에서 Zipkin Client 모듈로, 각 요청에 대해 ID를 자동으로 생성해줍니다.
이 ID 정보는 각 Protocol 의 Header 를 통해 전달되며, 정보를 수신한 서버는 다음 서버에게 동일한 정보를 제공하는 방식으로 히스토리를 추적할 수 있습니다.

공식 문서에 소개된 흐름에 대한 이미지를 보면, 최초 Request 가 발생한 시점부터 마지막 Reponse 가 발생할 때까지 모두 동일한 trace id 가 할당되고, 새로운 작업이 발생할 때마다 span id 는 계속 바뀌는 것을 볼 수 있습니다.

Trace Id Span Id
전체 작업에 할당된 ID.
작업은 각각의 작은 단위들로 구성되어 있다고 한다면, 각각의 작은 단위들은 공통의 Trace ID 를 갖고 있습니다.
각각의 작은 단위들이 가지고 있는 ID.
모두 서로 다른 ID 를 가지고 있기 때문에 서로 다른 작업 단위들을 구분해주는 역할을 할 수 있습니다.

Quick Start

Install Zipkin

Zipkin 을 설치한 후, java -jar로 실행시켜줍니다.

curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

dependency

Spring Cloud Starter Sleuth with Brave
Spring Cloud Starter Zipkin

// Maven
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>3.1.3</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.2.8.RELEASE</version>
</dependency>

// Gradle
dependencies {
	implementation 'org.springframework.cloud:spring-cloud-starter-sleuth:3.1.3'
    implementation 'org.springframework.cloud:spring-cloud-starter-zipkin:2.2.8.RELEASE'
}

application.yml

spring:
  sleuth: 
    sampler:
      probability: 1.0
  zipkin:
    base-url: http://localhost:9411
  • spring.sleuth.sampler.probability : 어플리케이션으로 오늘 요청 중 초당 몇 퍼센트나 트렌잭션 정보를 외부로 전달할지 설정. 0.0 ~ 1.0 값을 사용할 수 있으며 디폴트는 0.1 (10%)
  • spring.zipkin.base-url : 데이터를 전송할 zipkin 서버 url

log

추적할 대상에 대해 로그를 추가해줍니다.

// auth server
    @PostMapping("/account")
    public ResponseEntity<AuthLoginResponseDto> accountLogin(@Validated(AccountLoginValidation.class)
                                                             @RequestBody LoginRequestDto loginRequest,
                                                             HttpServletResponse httpServletResponse) {
        log.info("[REQUEST] account login");
        loginRequest.setAuthType(AuthType.ACCOUNT);
        return login(loginRequest, httpServletResponse);
    }

// user server
    @PostMapping("/login")
    public ResponseEntity<LoginResponseDto> login(@RequestBody LoginRequestDto loginRequest) {
        LoginResponseDto loginResponse = userService.handleLoginRequest(loginRequest);
        userService.updateUserAccessAt(loginResponse.getUserId());
        log.info("[REQUEST] account login");
        return getSuccessResponse(loginResponse);
    }

result

2022-07-31 15:25:20.146  INFO [user-service,c38013810200ffc0,c38013810200ffc0] 77031 --- [nio-9110-exec-2]

로그의 앞에 application name, trace ID, span ID 가 추가되어 나오는 것을 확인할 수 있습니다.
각 서버는 동일한 trace ID를 할당받고, 작업에 대해 각각의 span ID 를 할당받습니다.

Zipkin

이제 http://localhost:9411Zipkin에 접속해 서버명을 검색하면, 요청에 대한 플로우를 확인할 수 있습니다.

Ref.

Spring Cloud Sleuth
Spring Cloud Sleuth in a Monolith Application
Request Tracing in Microservices using Spring Cloud Sleuth and Zipkin
LINE 광고 플랫폼의 MSA 환경에서 Zipkin을 활용해 로그 트레이싱하기
Zipkin과 Sleuth를 활용한 분산 환경 로그 트레이싱
Zipkin을 이용한 MSA 환경에서 분산 트렌젝션의 추적 #1

profile
💻 + ☕ = </>