Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié)
分布式跟蹤允許您跟蹤分布式系統(tǒng)中的請(qǐng)求。本文通過了解如何使用 Spring Cloud Sleuth 和 Zipkin 來做到這一點(diǎn)。
對(duì)于一個(gè)做所有事情的大型應(yīng)用程序(我們通常將其稱為單體應(yīng)用程序),跟蹤應(yīng)用程序內(nèi)的傳入請(qǐng)求很容易。我們可以跟蹤日志,然后弄清楚請(qǐng)求是如何處理的。除了應(yīng)用程序日志本身之外,我們無需查看其他任何內(nèi)容。
隨著時(shí)間的推移,單體應(yīng)用程序變得難以擴(kuò)展,難以處理大量請(qǐng)求以及隨著代碼庫規(guī)模的不斷擴(kuò)大向客戶提供新功能。這導(dǎo)致將單體架構(gòu)分解為微服務(wù),這有助于擴(kuò)展單個(gè)組件并有助于更快地交付。
但并非所有閃耀的都是黃金,對(duì)吧?微服務(wù)也是如此。我們將整個(gè)單體系統(tǒng)拆分為微服務(wù),由一組本地函數(shù)調(diào)用處理的每個(gè)請(qǐng)求現(xiàn)在都被調(diào)用一組分布式服務(wù)所取代。這樣一來,我們就失去了追蹤在單體應(yīng)用中很容易完成的請(qǐng)求之類的事情。現(xiàn)在,要跟蹤每個(gè)請(qǐng)求,我們必須查看每個(gè)服務(wù)的日志,并且很難關(guān)聯(lián)。
因此,在分布式系統(tǒng)的情況下,分布式跟蹤的概念有助于跟蹤請(qǐng)求。
什么是分布式跟蹤?
分布式跟蹤是一種機(jī)制,我們可以使用它跟蹤整個(gè)分布式系統(tǒng)中的特定請(qǐng)求。它允許我們跟蹤請(qǐng)求如何從一個(gè)系統(tǒng)進(jìn)展到另一個(gè)系統(tǒng),從而完成用戶的請(qǐng)求。
分布式跟蹤的關(guān)鍵概念
分布式跟蹤包含兩個(gè)主要概念:
- 跟蹤 ID
- 跨度編號(hào)
跟蹤 id 用于跟蹤傳入請(qǐng)求并在所有組合服務(wù)中跟蹤它以滿足請(qǐng)求。Span id 跨越服務(wù)調(diào)用以跟蹤接收到的每個(gè)請(qǐng)求和發(fā)出的響應(yīng)。
讓我們看一下圖表。
傳入的請(qǐng)求沒有任何跟蹤 ID。攔截調(diào)用的第一個(gè)服務(wù)會(huì)生成跟蹤 ID“ID1”及其跨度 ID“A”。span id“B”涵蓋了從服務(wù)器一的客戶端發(fā)出請(qǐng)求到服務(wù)器二接收、處理并發(fā)出響應(yīng)的時(shí)間。
帶有 Spring Cloud Sleuth 的 Spring Boot 示例
讓我們創(chuàng)建一個(gè)集成了 Spring Cloud Sleuth 的應(yīng)用程序。首先,讓我們訪問https://start.spring.io/并使用依賴項(xiàng)“Spring Web”和“Spring Cloud Sleuth”創(chuàng)建一個(gè)應(yīng)用程序。
現(xiàn)在讓我們創(chuàng)建一個(gè)帶有兩個(gè)請(qǐng)求映射的簡單控制器。
public class Controller { private static final Logger logger = LoggerFactory.getLogger(Controller.class); private RestTemplate restTemplate; @Value("${spring.application.name}") private String applicationName; public Controller(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/path1") public ResponseEntity path1() { logger.info("Request at {} for request /path1 ", applicationName); String response = restTemplate.getForObject("http://localhost:8090/service/path2", String.class); return ResponseEntity.ok("response from /path1 + "+ response); @GetMapping("/path2") public ResponseEntity path2(){ logger.info("Request at {} at /path2", applicationName); return ResponseEntity.ok("response from /path2 "); }
在這里,我創(chuàng)建了兩條路徑,Path2調(diào)用Path2固定端口 8090。這里的想法是運(yùn)行同一應(yīng)用程序的兩個(gè)單獨(dú)實(shí)例。
現(xiàn)在為了允許偵探將標(biāo)頭注入到傳出請(qǐng)求中,我們需要將 RestTemplate 作為 bean 注入,而不是直接初始化它。這將允許偵探向 RestTemplate 添加一個(gè)攔截器,以將帶有跟蹤 id 和跨度 id 的標(biāo)頭注入到傳出請(qǐng)求中。
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); }
現(xiàn)在,讓我們啟動(dòng)兩個(gè)實(shí)例。為此,首先,構(gòu)建應(yīng)用程序,mvn clean verify然后運(yùn)行以下命令來啟動(dòng)“服務(wù) 1”。
java -jar \target/Distributed-Service-0.0.1-SNAPSHOT.jar \--spring.application.name=Service-1 \--server.port=8080
然后在不同的終端上運(yùn)行“服務(wù) 2”,如下所示:
java -jar \target/Distributed-Service-0.0.1-SNAPSHOT.jar \--spring.application.name=Service-2 \--server.port=8090
應(yīng)用程序啟動(dòng)后,調(diào)用“Service 1”,/path2如下所示:
curl -i http://localhost:8080/service/path1
現(xiàn)在讓我們看看“服務(wù)1”的日志。
INFO [Service-1,222f3b00a283c75c,222f3b00a283c75c] 41114 --- [nio-8080-exec-1] c.a.p.distributedservice.Controller : Incoming request at Service-1 for request /path1
日志包含方括號(hào),其中包含三個(gè)部分 [Service Name, Trace Id, Span Id]。對(duì)于第一個(gè)傳入的請(qǐng)求,由于沒有傳入的trace id,span id 與trace id 相同。
查看“服務(wù) 2”的?日志,我們看到我們?yōu)榇苏?qǐng)求有一個(gè)新的 span id。
INFO [Service-2,222f3b00a283c75c,13194db963293a22] 41052 --- [nio-8090-exec-1] c.a.p.distributedservice.Controller : Incoming request at Service-2 at /path2
我截獲了從“服務(wù) 1”發(fā)送到“服務(wù) 2”的??請(qǐng)求,并發(fā)現(xiàn)傳出的請(qǐng)求中已經(jīng)存在以下標(biāo)頭。
x-b3-traceid:"222f3b00a283c75c", x-b3-spanid:"13194db963293a22", x-b3-parentspanid:"222f3b00a283c75c
在這里,我們看到下一個(gè)操作(對(duì)“服務(wù) 2”的??調(diào)用)的跨度已經(jīng)注入到標(biāo)頭中。這些是在客戶端發(fā)出請(qǐng)求時(shí)由“服務(wù) 1”注入的。這意味著下一次調(diào)用“服務(wù) 2”的??跨度已經(jīng)從“服務(wù) 1”的客戶端開始。在上面顯示的標(biāo)題中,“服務(wù) 1”的 span id 現(xiàn)在是下一個(gè) span 的父 span id。
為了讓事情更容易理解,我們可以使用名為Zipkin的攔截器工具直觀地查看跟蹤。
使用 Zipkin 可視化跟蹤
要將 Zipkin 與應(yīng)用程序集成,我們需要向應(yīng)用程序添加 Zipkin 客戶端依賴項(xiàng)。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </dependency>
添加此依賴項(xiàng)后,Zipkin 客戶端默認(rèn)將跟蹤發(fā)送到 Zipkin 服務(wù)器的 9411 端口。讓我們使用其 docker 映像啟動(dòng) Zipkin 服務(wù)器。我為此創(chuàng)建了一個(gè)簡單的 docker-compose 文件。
version: "3.1" services: zipkin: image: openzipkin/zipkin:2 ports: - "9411:9411"
我們現(xiàn)在可以使用docker-compose up命令啟動(dòng)服務(wù)器。然后,您可以在以下位置訪問 UIhttp://localhost:9411/
由于我們使用的是默認(rèn)端口,我們不需要指定任何屬性,但是如果您打算使用不同的端口,則需要添加以下屬性。
spring: zipkin: baseUrl: http://localhost:9411
完成后,讓我們使用上面相同的命令啟動(dòng)兩個(gè)應(yīng)用程序。在向路徑中的“服務(wù) 1”發(fā)出請(qǐng)求時(shí),/path2我們會(huì)得到以下跟蹤。
這里顯示了兩個(gè)服務(wù)的跨度。我們可以通過查看跨度來更深入地挖掘。
“服務(wù) 1”的跨度是一個(gè)正常的跨度,涵蓋了它接收到返回響應(yīng)的請(qǐng)求。有趣的是第二個(gè)跨度。
在此,跨度中有四個(gè)點(diǎn)。
- 第一點(diǎn)是指來自“服務(wù)1”的客戶端何時(shí)開始請(qǐng)求。
- 第二點(diǎn)是“服務(wù) 2”開始處理請(qǐng)求的時(shí)間。
- 第三點(diǎn)是“Server 1”上的客戶端完成接收響應(yīng)的時(shí)間。
- 最后,“服務(wù)器 2”完成的最后一點(diǎn)。
因此,我們了解了如何將分布式跟蹤與 Spring Cloud Sleuth 集成,并使用 Zipkin 可視化跟蹤。
到此這篇關(guān)于Spring Cloud Sleuth 和 Zipkin 進(jìn)行分布式跟蹤使用指南的文章就介紹到這了,更多相關(guān)Spring Cloud Sleuth Zipkin 分布式跟蹤內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解JVM之Class類文件結(jié)構(gòu)詳解
這篇文章主要介紹了深入理解JVM之Class類文件結(jié)構(gòu),結(jié)合實(shí)例形式詳細(xì)分析了Class類文件結(jié)構(gòu)相關(guān)概念、原理、結(jié)構(gòu)、常用方法與屬性,需要的朋友可以參考下2019-09-09Java實(shí)現(xiàn)的數(shù)字簽名算法RSA完整示例
這篇文章主要介紹了Java實(shí)現(xiàn)的數(shù)字簽名算法RSA,結(jié)合完整實(shí)例形式詳細(xì)分析了RSA算法的相關(guān)概念、原理、實(shí)現(xiàn)方法及操作技巧,需要的朋友可以參考下2019-09-09Java中==與equals()及hashcode()三者之間的關(guān)系詳解
最近也是在讀Hollis的《深入理解Java核心技術(shù)》里面一節(jié)講到了equals()和hashcode()的關(guān)系,對(duì)于這個(gè)高頻面試點(diǎn),咱們需要認(rèn)真理清一下幾者之間的關(guān)系2022-10-10親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程
這篇文章主要介紹了親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09在SpringBoot中實(shí)現(xiàn)線程池并行處理任務(wù)的方法詳解
在使用Spring Boot開發(fā)應(yīng)用程序時(shí),我們經(jīng)常需要處理一些耗時(shí)的任務(wù),例如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫操作或者其他需要花費(fèi)一定時(shí)間的計(jì)算任務(wù),本文將介紹如何在Spring Boot中使用線程池來實(shí)現(xiàn)任務(wù)的并行處理2023-06-06@Transaction,@Async在同一個(gè)類中注解失效的原因分析及解決
這篇文章主要介紹了@Transaction,@Async在同一個(gè)類中注解失效的原因分析及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12MyBatis?Generator快速生成實(shí)體類和映射文件的方法
這篇文章主要介紹了MyBatis?Generator快速生成實(shí)體類和映射文件的方法,通過示例代碼介紹了MyBatis?Generator?的使用,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10