티스토리 뷰

MSA로 구성을 하면 어려워지는 기능 중 로그추적 기능이 있다. 기존의 Monolithic 구조에서는 로그 추적을 쉽게 할수 있었는데 app이 분산됨에 따라 어려워졌다. 하지만 훌륭한 로그 추적 솔루션들이 생기기 시작했고 우리는 그것을 잘 이용만 하면 된다. 

 

이번에 다루려고 하는 훌륭한 솔루션은 바로 Spring Cloud SleuthZipkin이다. 아주 간단하게 이것들에 대해서 설명을 하자면 Spring Cloud Sleuth는 각 어플리케이션에서 발생하는 로그들에 대해 trace id 를 부과하는 역할을 한다. trace id라 함은 서비스의 고유한 추적 ID라고 이해하면 된다. 이렇게 trace id가 생성이 되면 Zipkin은 trace id를 토대로 UI를 통해 추적을 용이하게 해주는 역할을 한다. 바로 어떻게 사용하는지에 대해 알아보자. 

 

참고로 Sleuth는 '슬루쓰' 라고 읽으며 탐정이라는 뜻을 가지고 있다. 추적을 한다는 의미와 잘 어울린다. 


Spring Cloud Sleuth 적용 (EurekaClient1, EurekaClient2)

예제는 기존에 구성해서 실습했던 EurekaClient라는 API Server로 계속 진행을 하겠다. 기본적인 구성은 여기를 참조하도록 하자. 

 

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>

로그 수집을 할 모든 app에 위와 같이 sleuth-zipkin 의존성을 추가해준다.  

 

 

SampleController.java (EurekaClient1)

@RequestMapping("/hello1")
public String printHelloWorld1() {
    log.info("This log was printed from application 1");
    return restTemplate.getForObject("http://oingdaddy2/hello3", String.class);
}

SampleController.java (EurekaClient2)

@RequestMapping("/hello3")
public String printHelloWorld3() {
    log.info("This log was printed from application 2");
    return "app1 to app2 Success";
}

바로 Controller에 method 하나 추가하고 /hello1을 호출을 해보자. 

기존에는 이런 식으로 출력이 되었던 로그가 

이런식으로 변경이 된것을 확인할 수 있다. 이 부분에 대해서는 아래에서 다시 보도록 하자

Sleuth가 잘 적용되어 로그에 대한 trace id를 잘 생성함을 확인할 수 있었다. 

 


Zipkin 설치 

Zipkin은 본래 분산로그추적이 주기능인 솔루션은 아니고 분산시스템 구간별 지연시간 측정을 위한 솔루션인데 이를 하기 위해서는 각 서비스를 연결하고 그를 위한 trace id가 필요했다. 이 trace id를 로그에 사용하면서 자연스럽게 분산로그추적의 기능도 사용할 수 있게 된 것이다. 

누르면 zipkin 다운로드 페이지로 이동

위의 그림을 눌러서 다운로드 페이지로 이동한다. Docker로 설치해도 되고 그냥 jar파일을 통해 실행해도 된다. 

 

zipkin 설치

> java -jar zipkin-server-2.22.1-exec.jar

실행은 cmd창을 열고 다운받은 jar파일이 있는 곳에서 위와 같이 입력하여 설치할 수 있다. 2.22.1 대신 자신이 받은 Zipkin의 버전을 입력해주면 된다. Zipkin의 기본 포트는 9411을 사용한다. foreground로 실행했기 때문에 cmd를 닫으면 Zipkin의 실행이 종료된다. 

 

Zipkin 첫 화면

실행은 시킨채로 브라우저에 127.0.0.1:9411을 입력하면 위와 같은 화면이 나온다면 성공적으로 설치가 된것이다.

 


Sleuth + Zipkin 연결 및 분산로그 Tracing

API Server와 Zipkin application의 연결은 application.yml (or application.properties) 파일에서 한다.

 

application.yml

spring:
  application:
    name: oingdaddy
  cloud:
    config:
      uri: 
      - http://localhost:8200
  sleuth:
    web:
      enabled: true
    sampler:
      probability: 1.0
  zipkin:
    base-url: http://localhost:9411

 

or application.properties

spring.application.name=oingdaddy
spring.sleuth.web.enabled=true
spring.sleuth.sampler.probability=1.0
spring.zipkin.baseUrl=http://localhost:9411

이렇게 설정을 한 후 각 app을 재기동한다. 그리고 아까와 같이 trace id가 찍히도록 /hello1 액션을 날려보자. 

 

app1 log

oingdaddy는 application name이고 두번째 파라미터인 f90a7b25bf9175d9 tracing id이다. 마이크로서비스간의 공통된 ID값이라고 생각하면 되고 세번째 파라미터인 b7484171420d9fc5 span id이다. 이것은 각 서비스의 고유한 ID값이라고 생각하면 된다. 그리고 마지막에 true는 Zipkin이나 다른 서비스에 전송 여부를 뜻한다.

이것은 EurekaClient1에서 찍힌 로그이고 EurekaClient2에서 찍힌 로그를 확인해보자. 

 

app2 log

EurekaClient2는 oingdaddy2라는 application name을 가지고 있다. 그리고 두번째 파라미터인 f90a7b25bf9175d9은 app1과 동일하다. 이것은 tracing id라고 했는데 이 값을 기준으로 transaction의 순서를 찾기 때문에 동일해야 한다. 또한 이것만의 span id가 생성된것을 확인할 수 있다. app1의 span id와 app2의 span id도 또한 눈여겨 봐두자. 

 

 

Zipkin에서 실행을 해보자. 

우측 상단에 trace id를 넣고 조회를 해보면 결과가 도출된다. 어떤 순서로 호출이 되었는지에 대한 정보가 쭉 나온다. 우측 중단에 span id의 정보들도 나오는데 oingdaddy2의 span id의 값은 무엇이고 이것을 호출한 녀석의 span id의 값은 또 무엇인지 알수 있다. 이런식으로 복잡한 호출관계에 있는 app간의 관계를 파악할 수 있다. 

 

결과에 대해 SHOW ALL ANNOTATIONS로 볼수도 있고 json 형식으로 받아서 한번에 볼수도 있다. 빨간네모친 중간에 DOWNLOAD JSON으로 받을수 있으며 다음과 같은 형식으로 출력이 된다. 

[{"traceId":"0b7ac76c6abc8c26","parentId":"079ffbd744c57084","id":"0c6f10d4e2d63a37","kind":"SERVER","name":"get /hello3","timestamp":1604289948019610,"duration":4441,"localEndpoint":{"serviceName":"oingdaddy2"},"remoteEndpoint":{"ipv4":"10.184.71.132","port":63505},"tags":{"http.method":"GET","http.path":"/hello3","mvc.controller.class":"SampleContoller2","mvc.controller.method":"printHelloWorld3"},"shared":true},{"traceId":"0b7ac76c6abc8c26","parentId":"079ffbd744c57084","id":"0c6f10d4e2d63a37","kind":"CLIENT","name":"get","timestamp":1604289948016017,"duration":7432,"localEndpoint":{"serviceName":"oingdaddy"},"tags":{"http.method":"GET","http.path":"/hello3"}},{"traceId":"0b7ac76c6abc8c26","parentId":"0b7ac76c6abc8c26","id":"079ffbd744c57084","name":"hystrix","timestamp":1604289948014844,"duration":11266,"localEndpoint":{"serviceName":"oingdaddy"}},{"traceId":"0b7ac76c6abc8c26","id":"0b7ac76c6abc8c26","kind":"SERVER","name":"get /hello1","timestamp":1604289948011622,"duration":16924,"localEndpoint":{"serviceName":"oingdaddy"},"remoteEndpoint":{"ipv4":"127.0.0.1","port":63528},"tags":{"http.method":"GET","http.path":"/hello1","mvc.controller.class":"SampleContoller","mvc.controller.method":"printHelloWorld1"}}]

이렇게 json으로 보관을 해뒀다가 나중에 우측 상단 빨간박스 옆에 업로드 모양을 통해 간편하게 볼수 있다. 

 

끝!

 

 

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31