λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ”¬μ•„ν‚€ν…μ²˜/- distributed system

[Distributed Tracing] Zipkin κ³Ό Spring Cloud Sleuth 에 λŒ€ν•΄μ„œ

by Wonit 2022. 5. 1.

 

λ³Έ 글은 λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€μ˜ λΆ„μ‚° 좔적 μ‹œλ¦¬μ¦ˆλ‘œ 이둠과 μ‹€μŠ΅μ΄ ν•¨κ»˜ ν¬ν•¨λœ μ‹œλ¦¬μ¦ˆμž…λ‹ˆλ‹€. μ•„λž˜ λͺ©μ°¨μ— ν‘œμ‹œλœ 글을 λͺ¨λ‘ μ°Έκ³ ν•˜λ©΄ μ’‹μŠ΅λ‹ˆλ‹€.

 

λͺ©μ°¨

 

 
μ‹€μŠ΅μ— λŒ€ν•œ μ†ŒμŠ€μ½”λ“œλ₯Ό ν™•μΈν•˜μ‹œκ³  μ‹Άλ‹€λ©΄ μ‹€μŠ΅ githubμ—μ„œ ν™•μΈν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.

 


Zipkin 에 λŒ€ν•΄μ„œ

 

Zipkin 은 νŠΈμœ„ν„°μ—μ„œ κ°œλ°œν•˜κ³  μ‚¬μš©ν•œ Distributed Tracing Tool 이닀

 

 

Zipkin μ—μ„œλŠ” μ§€λ‚œ μ‹œκ°„ μ—μ„œλ„ μ΄μ•ΌκΈ°ν•˜μ˜€λ˜ Dapper λ₯Ό μ΄μš©ν•˜μ—¬ λΆ„μ‚° ν™˜κ²½μ—μ„œ λ©”μ‹œμ§€λ₯Ό μΆ”μ ν•œλ‹€.

 

Zipkin μ—μ„œλŠ” Tracer 와 ν•¨κ»˜ν•΄μ•Ό ν•œλ‹€.

 

Tracer λŠ” 각 λ…Έλ“œμ— ν¬ν•¨λ˜μ–΄μžˆλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 라이브러리 ν˜Ήμ€ Sidecar 둜 ν•΄λ‹Ή λ…Έλ“œμ—μ„œ λ°œμƒν•œ λ©”μ‹œμ§€λ₯Ό Timing Data 와 같은 Metadata λ₯Ό ν¬ν•¨μ‹œμΌœ Zipkin 으둜 전솑해쀀닀.

 

그럼 Zipkin 에 ν¬ν•¨λœ Collector 에 μ˜ν•΄μ„œ ν•΄λ‹Ή 데이터듀이 λͺ¨μ΄κ²Œ 되고 μ •μ œλœλ‹€.

 

그런 λ’€ Zipkin 의 UI Dashboard μ—μ„œ 확인할 수 있게 ν•œλ‹€

 

Trace 와 Span

 

Zipkin μ—μ„œλŠ” λΆ„μ‚° ν™˜κ²½μ˜ λ©”μ‹œμ§€λ“€μ„ Trace 와 Span 을 ν†΅ν•΄μ„œ κ΅¬λΆ„ν•˜κ³  상관관계λ₯Ό κ·œμ •ν•œλ‹€

 

 

Span in Zipkin

 

Span은 Timing Data 와 같은 메타 데이터λ₯Ό ν¬ν•¨ν•˜λŠ” 정보이닀.

 

Span 에 ν¬ν•¨λœ λ°μ΄ν„°λŠ” κ³„μ†ν•΄μ„œ Zipkin Collector 둜 μ „μ†‘λ˜μ–΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— κ°€λŠ₯ν•œ μž‘κ²Œ μœ μ§€λ˜μ–΄μ•Ό ν•œλ‹€.

 

Span 은 μ„œλ‘œ μ—°κ²°λ˜μ–΄μžˆλŠ”λ°, SpanId 와 ParentSpanId λ₯Ό ν†΅ν•΄μ„œ λ…Όλ¦¬μ μœΌλ‘œ μ—°κ²°λ˜μ–΄μžˆλ‹€

 

Trace in Zipkin

 

Trace λŠ” Span λ“€μ˜ μ„ΈνŠΈλ‘œ ν•˜λ‚˜μ˜ TraceId λ₯Ό 각각의 Span 듀이 κ³΅μœ ν•˜λŠ” 방식이닀

 

μ΄λŸ¬ν•œ Span κ³Ό Trace 데이터가 Zipkin 에 μ „μ†‘λ˜λ©΄ λ‹€μŒκ³Ό 같은 json 으둜 Zipkin

 

  [
    {
      "traceId": "5982fe77008310cc80f1da5e10147517",
      "name": "get",
      "id": "bd7a977555f6b982",
      "localEndpoint": {
        "serviceName": "zipkin-query",
      },
      "annotations": [
        {
          "timestamp": 1458702548467000,
        },
        {
          "timestamp": 1458702548853000,
        }
      ]
    },
    {
      "traceId": "5982fe77008310cc80f1da5e10147517",
      "name": "get-traces",
      "id": "ebf33e1a81dc6f71",
      "parentId": "bd7a977555f6b982",
      "localEndpoint": {
        "serviceName": "zipkin-query",
      },
      "tags": {
        // μƒλž΅
      }
    }
  ]

 

Zipkin 의 μ•„ν‚€ν…μ²˜

 

 

Zipkin 은 크게 3κ°€μ§€μ˜ 파트둜 λ‚˜λ‰œλ‹€.

 

  1. Reporter
  2. Collector
  3. Storage & UI

 

Reporter

 

  • λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ λ…Έλ“œμ— ν¬ν•¨λ˜λ©° λ©”μ‹œμ§€κ°€ λ°œμƒν•  λ•Œλ§ˆλ‹€ ν•΄λ‹Ή λ©”μ‹œμ§€μ˜ Metadata λ₯Ό Zipkin Collector 둜 λΉ„λ™κΈ°μ μœΌλ‘œ μ „μ†‘ν•œλ‹€
  • Metadata μ—λŠ” Timing Data, TraceId, SpanId 와 같은 정보듀이 ν¬ν•¨λœλ‹€

 

Collector

 

  • λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ μ»΄ν¬λ„ŒνŠΈλŠ” zipkin daemon 으둜 데이터λ₯Ό μ „μ†‘ν•˜λŠ”λ° 이 데이터λ₯Ό λ°›λŠ” λͺ¨λ“ˆμ„ 컬렉터라고 λΆ€λ₯Έλ‹€.

 

Storage & UI

 

  • μΉ΄μ‚°λ“œλΌκ°€ 기본적인 Storage Infrastructure 둜 μ‚¬μš©λœλ‹€.
  • Plug & Play 방식이기 λ•Œλ¬Έμ— Cassandra 이외에도 Elastic Search & MySQL 을 연동할 수 μžˆλ‹€

 

Zipkin μ‹€ν–‰ν•˜κΈ°

 

zipkin 을 μ‹œμž‘ν•˜λŠ” 방법은 μ—¬λŸ¬κ°€μ§€ 방법이 μžˆκ² μ§€λ§Œ λ‚˜λŠ” docker λ₯Ό μ΄μš©ν•΄λ³΄λ € ν•œλ‹€.

 

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

 

을 ν†΅ν•΄μ„œ zipkin 을 μ‹€ν–‰ν•˜κ³  9411 포트둜 μ ‘κ·Όν•˜λ©΄ λ‹€μŒκ³Ό 같은 μ›Ή λŒ€μ‹œλ³΄λ“œκ°€ λ‚˜νƒ€λ‚˜κ²Œ λœλ‹€

 

 

Spring Cloud Sleuth

 

Zipkin κ³Ό ν•¨κ»˜ μ‚¬μš©λ˜λŠ” Tracer λŠ” λ§Žμ€ 것듀이 μ‘΄μž¬ν•œλ‹€.

 

κ³΅μ‹μ μœΌλ‘œ Zipkin 이 κ°œλ°œν•˜κ³  μš΄μ˜ν•˜λŠ” Zipkin Supported κ³Ό Open Source 둜 μš΄μ˜λ˜λŠ” Zipkin Community Supported κ°€ μžˆλ‹€.

 

  • Zipkin Supported
    • brave
    • zipkin-js
    • zipkin-go
  • Zipkin Cummunity Supported
    • spring cloud sleuth
    • tapper
    • appmetrics-zipkin
    • htrace

 

이 μ€‘μ—μ„œλ„ μš°λ¦¬λŠ” Zipkin 의 Brave B3-Propagation 의 Java κ΅¬ν˜„μ²΄μΈ Spring Cloud Sleuth 에 λŒ€ν•΄μ„œ μ•Œμ•„λ³Ό 것이닀.

 

Spring Cloud Sleuth λŠ” λΆ„μ‚° 좔적을 μœ„ν•œ Spring Boot 기반의 auth-configuration 을 μ œκ³΅ν•œλ‹€.

 

λŒ€ν‘œμ μΈ Sleuth 의 κΈ°λŠ₯에 λŒ€ν•΄ μ΄μ•ΌκΈ°ν•΄λ³΄μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€

 

  • Header Propagation 을 μ΄μš©ν•˜μ—¬ Trace 정보λ₯Ό κΈ°λ‘ν•œλ‹€.
  • TraceId, SpanId λ₯Ό μžλ™μœΌλ‘œ 생성해쀀닀.
  • Http 을 ν†΅ν•΄μ„œ Tracing 정보λ₯Ό Zipkin 으둜 μ „μ†‘ν•œλ‹€
  • Trace 에 λŒ€ν•œ 정보듀을 ν† λŒ€λ‘œ Log Integration 을 μ œκ³΅ν•œλ‹€

 

Spring Cloud Sleuth μ—μ„œ Tracer 와 Span

 

Sleuth μ—λŠ” 2κ°€μ§€μ˜ 핡심 μΈν„°νŽ˜μ΄μŠ€κ°€ μ‘΄μž¬ν•œλ‹€.

 

  1. Tracer
  2. Span

 

Tracer λŠ” Root Span 을 생성할 수 μžˆλ„λ‘ 도와쀀닀.

 

Span 은 ν•˜λ‚˜μ˜ μž‘μ—… λ‹¨μœ„λ‘œ νŠΉμ • λ…Έλ“œμ—μ„œ λ°œμƒν•˜λŠ” 일련의 κ³Όμ • (start & end) κ°€ Span 이 λœλ‹€.

 

Span 의 Lifecycle

 

  • start
    • Span 이 생성, μ‹œμž‘λ˜μ—ˆμŒμ„ μ˜λ―Έν•˜κ³  start timestamp κ°€ κΈ°λ‘λœλ‹€.
  • end
    • span 이 μ’…λ£Œλ˜μ—ˆμŒμ„ μ˜λ―Έν•˜κ³ , Span 의 Life state κ°€ end μƒνƒœμ—¬μ•Όλ§Œ Zipkin Collector 둜 전솑이 λœλ‹€.

 

보톡 Span 을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” Tracer λ₯Ό autowired ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.

 

public class A {

  @Autowired
  private Tracing tracing;

  public void doSomething() {
    Tracing current = tracing.current():
    // ...
  }
}

 

μœ„μ˜ λ‚΄μš©λ“€μ€ 이후에 μžˆμ„ μ‹€μŠ΅μ—μ„œ 쑰금 더 μžμ„Ένžˆ μ•Œμ•„λ³΄λŠ” κ²ƒμœΌλ‘œ ν•˜μž

 

Zipkin 으둜 Reporting ν•˜κΈ°

 

Spring Cloud Sleuth μ—μ„œ Span 이 λ‹«νžˆκ²Œ 되면 Zipkin μ„œλ²„λ‘œ Reporting 을 ν•œλ‹€.

 

이떄, Sleuth λ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ Reporting ν•˜λŠ” λ‘œμ§μ„ μš°λ¦¬κ°€ κ΅¬μ„±ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

 

RestTemplate, KafkaTemplate, KafkaListener, RedisTemplate λ₯Ό Bean 으둜 λ“±λ‘ν•œλ‹€λ©΄ BeanPostProcessor λ₯Ό ν†΅ν•΄μ„œ Sleuth κ°€ Reporting 을 μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

 

이 λ‹€μŒ μ‹œκ°„μ— μžˆμ„ Sleuth μ‹€μŠ΅μ—μ„œ λ³Ό 수 μžˆμ§€λ§Œ Sleuth λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” node-express ν™˜κ²½μ—μ„œλŠ” 이λ₯Ό 직접 κ΅¬ν˜„ν•΄μ„œ Reporting ν•œλ‹€

 

 

Sleuth λ₯Ό μ‚¬μš©ν•  경우 Zipkin 으둜 Report ν•˜λŠ” 과정은 AsyncRepoter 에 μ˜ν•΄ Asynchronous ν•˜κ²Œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— λ³Έ Transaction κ³ΌλŠ” λ¬΄κ΄€ν•˜κ²Œ λ™μž‘ν•œλ‹€.

 

이 말은 Reporting Span 정보가 μœ μ‹€λ  수 μžˆλ‹€λŠ” λ§μ΄λ―€λ‘œ μœ μ‹€μ— λŒ€ν•œ λŒ€λΉ„λ„ ν•„μš”ν•˜λ‹€

 

Log Integration

 

Sleuth λ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ μ‰½κ²Œ Log Integration 이 κ°€λŠ₯ν•˜λ‹€

 

Sleuth λ₯Ό μΆ”κ°€ν•˜κ²Œ λœλ‹€λ©΄ λ‹€μŒκ³Ό 같은 ν˜•μ‹μœΌλ‘œ λ‘œκ·Έκ°€ 찍히게 λœλ‹€.

 

 

즉,

 

[service-name], [trace-id], [span-id]

 

ν˜•νƒœλ‘œ 찍히게 λ˜λŠ”λ°, 이 말은 TraceId 둜 둜그λ₯Ό ꡬ뢄할 수 있게 λœλ‹€λŠ” 것이닀.

 

이 νŠΉμ„±μ„ μ΄μš©ν•΄μ„œ μΆ”ν›„ Kibana 와 같은 κ³³μ—μ„œλ„ 둜그λ₯Ό μ‰½κ²Œ 관리할 수 있게 λœλ‹€.

λŒ“κΈ€