Zipkin是一種分布式跟蹤系統,它有助於收集解決微服務架構中得延遲問題所需的時序數據,它管理這些數據的收集和查找。
1. 架構概述
跟蹤器存在於您的應用程序中,並記錄有關發生的操作的時間和元數據。他們經常使用庫,因此它們的使用對用戶是透明的。例如,已檢測的Web服務器會在收到請求時以及何時發送響應時進行記錄。收集的跟蹤數據稱為Span。
編寫儀器是為了安全生產並且開銷很小。出於這個原因,它們只在帶內傳播ID,以告訴接收器正在進行跟蹤。Zipkin帶外報告已完成的跨度,類似於應用程序異步報告度量標准的方式。
例如,在跟蹤操作並且需要發出傳出的http請求時,會添加一些標頭來傳播ID。標頭不用於發送操作名稱等詳細信息。
將數據發送到Zipkin的檢測應用程序中的組件稱為Reporter。記者通過幾種傳輸之一將跟蹤數據發送到Zipkin收集器,這些收集器將跟蹤數據保存到存儲中。稍后,API會查詢存儲以向UI提供數據。
描述此流程,如下圖表:
Zipkin作為一個收藏家,一旦跟蹤數據到達Zipkin收集器守護程序,它就會被Zipkin收集器驗證,存儲和索引查找。
Zipkin查詢服務,一旦數據被存儲和索引,我們需要一種方法來提取它。查詢守護程序提供了一個簡單的JSON API,用戶查找和檢索跟蹤。
參考官網:https://zipkin.io/
2. 快速開始
本文,我們將介紹構建和啟動Zipkin實例,以便在本地檢查Zipkin。根據官網顯示,有三種選擇:使用Java、Docker或從源代碼運行。
如果您熟悉Docker,這是首選的方法。如果您不熟悉Docker,請嘗試通過Java或源代碼運行。
Zipkin分為兩端,一個是Zipkin服務端,一個是Zipkin客戶端(微服務應用)。客戶端會配置服務端的URL地址,一旦服務間調用的時候,會被配置在微服務里面的Sleuth的監聽器監聽,並生成相應的Trace和Span信息發送給服務端。
發送的方式主要有兩種,一種是Http報文的方式,還有一種是消息總線的方式如:RabbitMQ
我們這邊采用的是Http報文的方式。
Zipkin服務端構建
1. 引入依賴
解析:主要引入兩個Jar:zipkin-server、zipkin-autoconfigure-ui,其中對應的版本為:2.12.2。
zipkin-server 本身包含了 log4j,如果系統已經引入log4j包,為了避免沖突,需要在此處將本jar包去除。
<dependencies> <!-- zipkin server --> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </exclusion> </exclusions> <version>${zipkin}</version> </dependency> <!-- zipkin ui --> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> <version>${zipkin}</version> </dependency> </dependencies>
2. 配置文件
spring: application: name: zipkin-server security: user: name: zhangsan password: 111111 --- # 服務端口 server: port: 9411 --- eureka: instance: # 解決健康節點權限問題 將用戶名及密碼放入eureka的元數據中 metadata-map: user.name: ${spring.security.user.name} user.password: ${spring.security.user.password} client: service-url: defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@peer1:8761/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@peer2:8762/eureka/ --- # 客戶端負載均衡器 ribbon: ConnectTimeout: 3000 # 客戶端連接超時 ReadTimeout: 60000 # 客戶端讀取超時 MaxAutoRetries: 1 # 當前環境最大重試次數 MaxAutoRetriesNextServer: 2 # 其他環境最大重試次數 eureka: enabled: true --- hystrix: command: default: execution: timeout: enabled: false --- # 關閉自動配置啟用所有請求得檢測 management: metrics: web: server: auto-time-requests: true
注:如果配置文件中沒有添加“management.metrics.web.server.auto-time-requests=false”,默認為 開啟自動檢測請求
在啟動zipkin-server過程中,會報以下問題:
java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter containing tag keys [method, status, uri]. The meter you are attempting to register has keys [exception, method, status, uri].
解決方案:
a、配置文件中增加:management.metrics.web.server.auto-time-requests=false設置為false,默認為true
b、重寫WebMvcTagsProvider,目的是去掉 WebMvcTags.exception(exception)
package com.sinosoft.config; import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tags; import org.springframework.boot.actuate.metrics.web.servlet.WebMvcTags; import org.springframework.boot.actuate.metrics.web.servlet.WebMvcTagsProvider; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @ClassName: MyTagsProvider * @Description: TODO * @author: Created by xxx <a href="xxx@163.com">Contact author</a> * @date: 2019/2/27 13:49 * @Version: V1.0 */ public class MyTagsProvider implements WebMvcTagsProvider { /** * 去掉WebMvcTags.exception(exception) * * @param request 請求 * @param response 響應 * @param handler 處理 * @param exception 異常 * @return */ @Override public Iterable<Tag> getTags(HttpServletRequest request, HttpServletResponse response, Object handler, Throwable exception) { return Tags.of(WebMvcTags.method(request), WebMvcTags.uri(request, response), WebMvcTags.status(response)); } @Override public Iterable<Tag> getLongRequestTags(HttpServletRequest request, Object handler) { return Tags.of(WebMvcTags.method(request), WebMvcTags.uri(request, null)); } }
然后將重寫后的MyTagsProvider進行Bean注入
package com.sinosoft.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @ClassName: TagsProvideBean * @Description: TODO * @author: Created by xxx <a href="xxx@163.com">Contact author</a> * @date: 2019/2/27 13:54 * @Version: V1.0 */ @Configuration public class TagsProvideBean { /** * 將MyTagsProvider注入 * * @return */ @Bean public MyTagsProvider myTagsProvider() { return new MyTagsProvider(); } }
4. 啟動zipkin-server服務
package com.sinosoft; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import zipkin2.server.internal.EnableZipkinServer; /** * @ClassName: ZipkinApplication * @Description: 調用鏈服務啟動入口 * @author: Created by xxx <a href="xxx@163.com">Contact author</a> * @date: 2019/2/27 11:43 * @Version: V1.0 */ @SpringBootApplication @EnableDiscoveryClient @EnableZipkinServer public class ZipkinApplication { public static void main(String[] args) { SpringApplication.run(ZipkinApplication.class, args); } }
Zipkin客戶端構建
1. 引入依賴
<!-- 調用鏈 ZipKin --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
注:spring-cloud-starter-zipkin 已經包含了 spring-cloud-starter-sleuth
2. 配置文件
--- # 調用鏈 Sleuth + ZipKin spring: sleuth: web: client: enabled: true sampler: probability: 1.0 # 采用比例,默認 0.1 全部采樣 1.0 zipkin: base-url: http://localhost:9411/ # 指定了Zipkin服務器的地址
Zipkin效果展示
zipkin服務端及客戶端啟動之后,訪問:http://localhost:9411/zipkin/
默認是查找所有的服務對應的鏈路,如果需要查詢指定服務的鏈路跟蹤情況,可以選擇對應的服務名、Span名稱等其他條件,點擊查詢即可顯示本服務下的鏈路跟蹤結果。
鏈路跟蹤明細: