隨着業務發展,系統拆分致使系統調用鏈路愈發複雜一個前端請求可能最終須要調用不少次後端服務才能完成,當整個請求陷入性能瓶頸或不可用時,咱們是沒法得知該請求是由某個或某些後端服務引發的,這時就須要解決如何快讀定位服務故障點,以對症下藥。因而就有了分佈式系統調用跟蹤的誕生。 Spring Cloud Sleuth 也爲咱們提供了一套完整的解決方案。在本文中,咱們將詳細介紹如何使用 Spring Cloud Sleuth + Zipkin 來爲咱們的微服務架構增長分佈式服務跟蹤的能力。html
Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud, borrowing heavily from Dapper, Zipkin and HTrace. For most users Sleuth should be invisible, and all your interactions with external systems should be instrumented automatically. You can capture data simply in logs, or by sending it to a remote collector service.前端
Spring Cloud Sleuth是Spring Cloud實施分佈式跟蹤解決方案,大量借用Dapper,Zipkin和HTrace。 對於大多數用戶來講,偵探應該是隱形的,而且全部與外部系統的交互都應該自動進行檢測。 您能夠簡單地在日誌中捕獲數據,也能夠將數據發送到遠程收集器服務。java
SpringCloudSleuth 借用了 Dapper 的術語:mysql
Spring Cloud Sleuth 爲服務之間調用提供鏈路追蹤。經過 Sleuth 能夠很清楚的瞭解到一個服務請求通過了哪些服務,每一個服務處理花費了多長。從而讓咱們能夠很方便的理清各微服務間的調用關係。此外 Sleuth 能夠幫助咱們:git
- 耗時分析:經過 Sleuth 能夠很方便的瞭解到每一個採樣請求的耗時,從而分析出哪些服務調用比較耗時;
- 可視化錯誤:對於程序未捕捉的異常,能夠經過集成 Zipkin 服務界面上看到;
- 鏈路優化:對於調用比較頻繁的服務,能夠針對這些服務實施一些優化措施。
Spring Cloud Sleuth 能夠結合 Zipkin,將信息發送到 Zipkin,利用 Zipkin 的存儲來存儲信息,利用 Zipkin UI 來展現數據。github
這是 Spring Cloud Sleuth 的概念圖: web
只須要在pom.xml的dependencies中添加以下依賴,就能夠爲應用整合sleuth:spring
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
整合完成以後,啓動項目,調用一個請求(我人爲的關閉了應用要調用的另外一個微服務,致使了請求失敗),這是看控制檯日誌:sql
2019-10-29 16:28:57.417 INFO [study01,,,] 5830 --- [-192.168.31.101] o.s.web.servlet.DispatcherServlet : Completed initialization in 27 ms 2019-10-29 16:28:57.430 INFO [study01,,,] 5830 --- [-192.168.31.101] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2019-10-29 16:28:57.433 INFO [study01,,,] 5830 --- [-192.168.31.101] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2019-10-29 16:28:58.520 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.e.s.feignClient.CommentFeignClient : [CommentFeignClient#find] ---> GET http://study02/find HTTP/1.1 2019-10-29 16:28:58.520 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.e.s.feignClient.CommentFeignClient : [CommentFeignClient#find] ---> END HTTP (0-byte body) 2019-10-29 16:28:58.520 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.s.i.w.c.f.TraceLoadBalancerFeignClient : Before send 2019-10-29 16:28:58.646 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.netflix.config.ChainedDynamicProperty : Flipping property: study02.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647 2019-10-29 16:28:58.661 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.netflix.loadbalancer.BaseLoadBalancer : Client: study02 instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=study02,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null 2019-10-29 16:28:58.667 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater 2019-10-29 16:28:58.683 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client study02 initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=study02,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@591b62cf 2019-10-29 16:28:58.707 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] o.s.c.s.i.a.ContextRefreshedListener : Context successfully refreshed 2019-10-29 16:28:58.755 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.s.i.w.c.f.TraceLoadBalancerFeignClient : Exception thrown
能夠看見日誌的形式和以前不太同樣了,首先啓動日誌裏面多了箇中括號:[study01,,,];而當應用請求報異常的時候,中括號中有了這些數據:[study01,42d9bd786504f775,42d9bd786504f775,false] study01是應用名稱,42d9bd786504f775是 trace ID,42d9bd786504f775是span ID,false表示是否是要把這條數據上傳給zipkin。這時,就能夠經過日誌分析應用哪裏出了問題、哪一個階段出了問題。後端
**PS:**能夠在應用中添加以下配置:
logging: level: org.springframework.cloud.sleuth: debug
這段配置的用處是讓sleuth打印更多的日誌,從而進一步幫助咱們分析錯誤【我上面粘出的日誌就是添加配置以後的結果】。
Zipkin 是 Twitter 的開源分佈式跟蹤系統,它基於 Google Dapper 實現,它致力於收集服務的時序數據,以解決微服務架構中的延遲問題,包括數據的收集、存儲、查找和展示。
curl -sSL https://zipkin.io/quickstart.sh | bash -s
訪問以下地址下載: https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec
下載完成以後,在下載的jar所在目錄,執行java -jar *****.jar
命令便可啓動Zipkin Server 訪問http://localhost:9411 便可看到Zipkin Server的首頁。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
PS:當使用了spring-cloud-starter-zipkin以後,前面添加spring-cloud-starter-sleuth就不須要了,由於前者包含了後者。
spring: zipkin: base-url: http://localhost:9411/ sleuth: sampler: # 抽樣率,默認是0.1(90%的數據會被丟棄) # 這邊爲了測試方便,將其設置爲1.0,即全部的數據都會上報給zipkin probability: 1.0
啓動項目,產生請求以後,打開zipkin控制檯,能夠剛剛請求的信息(按耗時降序排列):
點擊能夠查看請求的詳情:
這張圖中,Server Start表示的是Server Received;Server Finish表示的是Server Sent。 由於客戶端發生在瀏覽器上,而瀏覽器並無整合zipkin,因此zipkin中沒有Client Sent和Client Received數據。
前面搭建Zipkin是基於內存的,若是Zipkin發生重啓的話,數據就會丟失,這種方式是不適用於生產的,因此咱們須要實現數據持久化。 Zipkin給出三種數據持久化方法:
相關的官方文檔:https://github.com/openzipkin/zipkin#storage-component , 本文將介紹Elasticsearch實現Zipkin數據持久化
咱們須要下載什麼版本的Elasticsearch呢,官方文檔給出了建議,5-7版本均可以使用(本文使用的是Elasticsearch6.8.2,由於Elasticsearch7開始後須要jdk11支持):
The Elasticsearch component uses Elasticsearch 5+ features, but is tested against Elasticsearch 6-7.x.
下載完成後,解壓縮軟件包,進入bin目錄,執行 ./elasticsearch
便可啓動Elasticsearch:
訪問http://localhost:9200/
,出現以下頁面,說明Elasticsearch啓動成功:
zipkin提供了不少的環境變量,配置環境變量就能夠將數據存儲進Elasticsearch。
- STORAGE_TYPE: 指定存儲類型,可選項爲:mysql, cassandra, elasticsearch
- ES_HOSTS:Elasticsearch地址,多個使用,分隔,默認http://localhost:9200
- ES_PIPELINE:指定span被索引以前的pipeline(Elasticsearch的概念)
- ES_TIMEOUT:鏈接Elasticsearch的超時時間,單位是毫秒;默認10000(10秒)
- ES_INDEX:zipkin所使用的索引前綴(zipkin會天天創建索引),默認zipkin
- ES_DATE_SEPARATOR:zipkin創建索引的日期分隔符,默認是-
- ES_INDEX_SHARDS:shard(Elasticsearch的概念)個數,默認5
- ES_INDEX_REPLICAS:副本(Elasticsearch的概念)個數,默認1
- ES_USERNAME/ES_PASSWORD:Elasticsearch帳號密碼
- ES_HTTP_LOGGING:控制Elasticsearch Api的日誌級別,可選項爲BASIC、HEADERS、BODY
更多環境變量參照:https://github.com/openzipkin/zipkin/tree/master/zipkin-server#environment-variables
執行下面代碼從新啓動zipkin:
STORAGE_TYPE=elasticsearch ES_HOSTS=localhost:9200 java -jar zipkin-server-2.12.9-exec.jar
產生請求以後,訪問http://localhost:9411/zipkin/,能夠看見剛剛請求的數據:
停調zipkin,而後再次啓動,訪問http://localhost:9411/zipkin/,能夠看見數據依然存在:
說明此時,數據已經實現了持久化。
從官方文檔能夠看出,使用Elasticsearch進行zipkin數據持久化以後,Zipkin的依賴關係分析功能沒法使用了。
Note: This store requires a spark job to aggregate dependency links. 咱們須要整合zipkin-dependencies來實現依賴關係圖功能。zipkin-dependencies是zipkin的一個子項目,啓動很是的簡單。
下載: curl -sSL https://zipkin.io/quickstart.sh | bash -s io.zipkin.dependencies:zipkin-dependencies:LATEST zipkin-dependencies.jar 啓動: STORAGE_TYPE=elasticsearch ES_HOSTS=localhost:9200 java -jar zipkin-dependencies.jar
- STORAGE_TYPE: 指定存儲類型,可選項爲:mysql, cassandra, elasticsearch
- ES_HOSTS:Elasticsearch地址,多個使用,分隔,默認http://localhost:9200
- ES_INDEX:zipkin所使用的索引前綴(zipkin會天天創建索引),默認zipkin
- ES_DATE_SEPARATOR:zipkin創建索引的日期分隔符,默認是-
- ES_NODES_WAN_ONLY:若是設爲true,則表示僅使用ES_HOSTS所設置的值,默認爲false。當Elasticsearch集羣運行在Docker中時,可將該環境變量設爲true。
這邊只須要把項目啓動,就能夠展現依賴關係圖了,這裏就再也不演示了。 **注意:**zipkin-dependencies啓動以後會自動中止,因此建議使用定時任務讓操做系統定時啓動zipkin-dependencies。
分析昨天的數據(OS/X下的命令) STORAGE_TYPE=elasticsearch java -jar zipkin-dependencies.jar 'date -uv-ld + %F' 分析昨天的數據(Linux下的命令) STORAGE_TYPE=elasticsearch java -jar zipkin-dependencies.jar 'date -u -d '1 day ago' + %F' 分析指定日期的數據 STORAGE_TYPE=elasticsearch java -jar zipkin-dependencies.jar 2019-10-29
原文出處:https://www.cnblogs.com/fx-blog/p/11757124.html