boot接入zipkin


zipkin接入

Zipkin是一種分布式跟蹤系統。它有助於收集解決微服務架構中的延遲問題所需的時序數據。它管理這些數據的收集和查找。Zipkin的設計基於 Google Dapper論文,對原理感興趣可以看下。

1 zipkin簡介

1.1 作用

簡單說就是采集各服務之間互相調用的信息:誰調用了誰,調用是否發生故障,調用耗時多少。並提供可視化界面。方便快速定位服務故障點。

1.2 原理

zipkin架構圖如下所示:

Trace

Zipkin使用Trace結構表示對一次請求的跟蹤,一次請求可能由后台的若干服務負責處理,每個服務的處理是一個Span,Span之間有依賴關系,Trace就是樹結構的Span集合;

Span

每個服務的處理跟蹤是一個Span,可以理解為一個基本的工作單元,包含了一些描述信息:id,parentId,name,timestamp,duration,annotations等

Components

有4個組件組成Zipkin:collector,storage,search,web UI
collector:一旦跟蹤數據到達Zipkin collector守護進程,它將被驗證,存儲和索引,以供Zipkin收集器查找;
storage:Zipkin最初數據存儲在Cassandra上,因為Cassandra是可擴展的,具有靈活的模式,並在Twitter中大量使用;但是這個組件可插入,除了Cassandra之外,還支持ElasticSearch和MySQL;
search:一旦數據被存儲和索引,我們需要一種方法來提取它。查詢守護進程提供了一個簡單的JSON API來查找和檢索跟蹤,主要給Web UI使用;
web UI:創建了一個GUI,為查看痕跡提供了一個很好的界面;Web UI提供了一種基於服務,時間和注釋查看跟蹤的方法。

支持跟蹤的請求類型

  • 通過mq技術(如Apache Kafka或RabbitMQ)(或任何其他Spring Cloud Stream binder)進行的請求。
  • 在Spring MVC controller收到的HTTP header。
  • 通過Netflix Zuul傳過來的microroxy請求。
  • 使用RestTemplate等進行的請求。

埋點實現:主要通過filter,aop等攔截技術,獲取到Span信息,通過Transport(有三個主要的傳輸方式:Http、kafka和Scribe)異步發送給zipkin服務器。

zipkin支持mysql、cassandra、elasticsearch幾種存儲方案。mysql性能可能有點問題,建議后期改es做持久化。

1.3 使用場景

隨着業務越來越復雜,服務也隨之拆分。一個前端的請求可能需要多次的服務調用最后才能完成。為了獲取服務之間相互依賴信息,以及各服務之間的調用情況。方便快速定位服務故障點,接入zipkin。

2 zipkin服務器

項目地址:https://github.com/huanghuizhou/zipkin-demo.git

開發接入無需關心。

啟動后訪問 http://192.168.1.172:9411

3 項目接入zipkin

3.1 maven依賴

		<!--zipkin鏈路追蹤-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

3.2 配置文件

application.yml 加入下面配置

spring:
  zipkin:
    base-url: http://192.168.1.172:9411
  sleuth:
    sampler:
    	#采集比例 默認0.1 只采集10%
      probability: 0.1

4 坑點

4.1 局部變量RestTemplate無法形成調用鏈

 @Bean
public RestTemplate getRestTemplate(){
    return new RestTemplate();
}

@Autowired
private RestTemplate restTemplate;
public void test(){
    ResponseEntity<Object> response = restTemplate.exchange("http://localhost:9500/message/smsLoad?pageSize=10&pageNum=1", HttpMethod.GET, null, Object.class);
}

通過bean 注入restTemplate時能正常形成調用鏈。span深度為2。

如下圖:

服務之間依賴如下圖:

 public void test1(){
        RestTemplate restTemplate=new RestTemplate();
        ResponseEntity<Object> response = restTemplate.exchange("http://localhost:9500/message/smsLoad?pageSize=10&pageNum=1", HttpMethod.GET, null, Object.class);
        System.out.println(111);
    }

通過局部變量RestTemplate 進行調用,無法形成調用鏈。span深度為1。

如下圖:

形成兩個單獨的調用記錄。

服務之間依賴如下圖:

看了zipkin brave的部分源碼。4.1 局部變量RestTemplate 無法形成調用鏈的原因大致如下:

zipkin的信息埋點是在方法執行完后進行的。例:A同步調用B,B服務先執行完向zipkin服務器發送數據。然后A調用完B執行完A的后續方法后,然后也向zipkin服務器發送信息。埋點順序是 B-A。

zipkin的brave TracingClientHttpRequestInterceptor實現了ClientHttpRequestInterceptor接口,會對RestTemplate 的bean進行攔截,
並獲取到restTemplate返回的response信息從而形成一個調用鏈。通過局部變量RestTemplate沒有接入TracingClientHttpRequestInterceptor
攔截器進行攔截,A調用完B后無法獲取到B的返回信息,因此A向zipkin發送信息時沒有B返回的信息,無法形成調用鏈。

TracingClientHttpRequestInterceptor部分源碼如下:

@Override public ClientHttpResponse intercept(HttpRequest request, byte[] body,
    ClientHttpRequestExecution execution) throws IOException {
  Span span = handler.handleSend(injector, request.getHeaders(), request);
  ClientHttpResponse response = null;
  Throwable error = null;
  try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
    return response = execution.execute(request, body);
  } catch (IOException | RuntimeException | Error e) {
    error = e;
    throw e;
  } finally {
    handler.handleReceive(response, error, span);
  }
}

spring cloud feign客戶端以bean的形式存在,無需擔心此問題。

4.2 采集率以調用鏈首個服務為主

例:A采集率10%,B采集率100%。 A調用B形成一個調用鏈。 只有10%概率會被采集到zipkin服務器上。
反之亦凡。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM