Zipkin
Zipkin
是一個分佈式跟蹤系統,用於收集、管理和查找跟蹤數據。它可以把分佈式鏈路調用的順序串起來,並計算鏈路中每個 RPC
調用的耗時,可以很直觀的看出在整個調用鏈路中延遲問題。 Zipkin
的設計基於 GoogleDapper
論文實現的。
ZipkinServer
提供了 UI
操作,可以非常方便地查看和搜索跟蹤數據,直觀的查看到鏈調用依賴關係。
該項目包括一個無依賴庫和一個 spring-boot
服務器。存儲支持包括內存, JDBC(mysql)
, Cassandra
和 Elasticsearch
。
在沒有使用外部存儲時,則默認使用內存存儲數據,內存數據是有限且不可持久化的,所以建議使用外部存儲,因日誌數據通常很大,爲了搜索日誌的效率,所以建議使用 Elasticsearch
。
Zipkin 的基礎架構由 4 個核心組件構成:
Collector
:收集器組件,處理從外部系統發過來的跟蹤信息,將這些信息轉換爲 Zipkin 內部處理的 Span 格式,以支持後續的存儲、分析、展示等功能。Stroage
:存儲組件,主要處理收集器收到的跟蹤信息,默認存儲在內存中,也可通過 ES 或 JDBC 來存儲。Restful API
:API 組件,提供外部訪問接口。Web UI
:UI組件,基於 API 組件實現的 Web 控制檯,用戶可以很方便直觀地查詢、搜索和分析跟蹤信息。
部署測試服務
使用 docker
部署本地 zipkin
的 server
端
docker run -d -p 9411:9411 \
--name zipkin \
docker.io/openzipkin/zipkin
訪問:http://localhost:9411/zipkin/
構建測試項目
-
Service A
server: port: 8081 spring: application: name: server-a sleuth: web: client: enabled: true sampler: probability: 1.0 # 採用比例,默認 0.1 全部採樣 1.0 zipkin: base-url: http://localhost:9411/ # 指定了Zipkin服務器的地址
@Slf4j @RestController public class ServiceAController { @Resource private RestTemplate restTemplate; @GetMapping(value = "/servicea") public String servicea() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("This is service a!"); return restTemplate.getForObject("http://localhost:8082/serviceb", String.class); } }
-
Service B
server: port: 8082 spring: application: name: server-b sleuth: web: client: enabled: true sampler: probability: 1.0 # 採用比例,默認 0.1 全部採樣 1.0 zipkin: base-url: http://localhost:9411/ # 指定了Zipkin服務器的地址
@Slf4j @RestController public class ServiceBController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/serviceb") public String serviceb() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("This is service b!"); return restTemplate.getForObject("http://localhost:8083/servicec", String.class); } }
-
Service C
server: port: 8083 spring: application: name: server-c sleuth: web: client: enabled: true sampler: probability: 1.0 # 採用比例,默認 0.1 全部採樣 1.0 zipkin: base-url: http://localhost:9411/ # 指定了Zipkin服務器的地址
@Slf4j @RestController public class ServiceCController { @Resource private RestTemplate restTemplate; @GetMapping(value = "/servicec") public String servicec() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("This is service c!"); return "hello,this is server c!"; } }
測試服務調用鏈-Sleuth
Zipkin
的依賴中包含了 Sleuth
,Sleuth
功能:
- 將
SpanID
和TraceID
添加到Slf4JMDC
中,這樣可以在日誌聚合器中根據SpanID
和TraceID
提取日誌。 - 提供對常見分佈式跟蹤數據模型的抽象:
traces(跟蹤)
,spans(形成DAG(有向無環圖))
,註釋,key-value
註釋。鬆散地基於HTrace
,但兼容Zipkin(Dapper)
。 Sleuth
常見的入口和出口點來自Spring
應用(Servlet
過濾器、Rest Template
、Scheduled Actions
、消息通道、Zuul Filter、
Feign Client`)。- 如果
spring-cloud-sleuth-zipkin
可用,Sleuth
將通過HTTP
生成並收集與Zipkin
兼容的跟蹤。默認情況下,將跟蹤數據發送到localhost
(端口:9411)上的Zipkin
收集服務應用,可使用spring.zipkin.baseUrl
修改服務器地址。
啓動3個服務,訪問:http://localhost:8081/servicea
,可以看到3個服務的日誌輸出如下:
在輸出的日誌中,多了些內容,這些內容就是由 sleuth
爲服務調用提供的鏈路信息
可以看到內容組成:[appname,traceId,spanId,exportable]
,具體含義如下:
appname
:服務的名稱,即 spring.application.name 的值。traceId
:整個請求鏈路的唯一ID。spanId
:基本的工作單元,一個 RPC 調用就是一個新的 span。啓動跟蹤的初始 span 稱爲 root span ,此 spanId 的值與 traceId 的值相同。見上面示例消費者服務日誌輸出。exportable
:是否將數據導入到 Zipkin 中,true 表示導入成功,false 表示導入失敗。
Zipkin Server
再次訪問:http://localhost:9411/zipkin/
,點擊查詢,可以看到剛纔執行的服務調用鏈:
點擊可以看到具體的調用時間與鏈路:
點擊具體的服務,可以看到服務調用的詳情以及父級子級 trace