具有關聯ID的統一日志記錄平台是一個強大的調試工具。但是,在本章的剩余部分中,我們將不再關注如何跟蹤日志條目,而是關注如何跨不同微服務可視化事務流。一張干凈簡潔的圖片比一百萬條日志條目有用。
分布式跟蹤涉及提供一張可視化的圖片,說明事務如何流經不同的微服務。分布式跟蹤工具還將對單個微服務響應時間作出粗略的估計。但是,分布式跟蹤工具不應該與成熟的應用程序性能管理(Application Performance Management,APM)包混淆。這些包可以為服務中的實際代碼提供開箱即用的低級性能數據,除了提供響應時間,它還能提供其他性能數據,如內存利用率、CPU利用率和I/O利用率。
這就是Spring Cloud Sleuth和OpenZipkin(也稱為Zipkin)項目的亮點。Zipkin是一個分布式跟蹤平台,可用於跟蹤跨多個服務調用的事務。Zipkin允許開發人員以圖形方式查看事務占用的時間量,並分解在調用中涉及的每個微服務所用的時間。在微服務架構中,Zipkin是識別性能問題的寶貴工具。
建立Spring Cloud Sleuth和Zipkin涉及4項操作:
將Spring Cloud Sleuth和Zipkin JAR文件添加到捕獲跟蹤數據的服務中;
在每個服務中配置Spring屬性以指向收集跟蹤數據的Zipkin服務器;
安裝和配置Zipkin服務器以收集數據;
定義每個客戶端所使用的采樣策略,便於向Zipkin發送跟蹤信息。
9.3.1 添加Spring Cloud Sleuth和Zipkin依賴項
到目前為止,我們已經將兩個Maven依賴項包含到Zuul服務、許可證服務以及組織服務中。這些JAR文件是 spring-cloud-starter-sleuth和spring-cloud-sleuth-core依賴項。spring-cloud-starter-sleuth依賴項用於包含在服務中啟用Spring Cloud Sleuth所需的基本Spring Cloud Sleuth庫。當開發人員必須要以編程方式與Spring Cloud Sleuth進行交互時,就需要使用 spring-cloud-sleuth-core依賴項(本章后面將再次使用它)。
要與Zipkin集成,需要添加第二個Maven依賴項,名為spring-cloud-sleuth-zipkin。代碼清單9-3展示了添加spring-cloud-sleuth-zipkin依賴項后,在Zuul、許可證以及組織服務中應該存在的Maven條目。
代碼清單9-3 客戶端的Spring Cloud Sleuth和Zipkin依賴項
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
9.3.2 配置服務以指向Zipkin
有了JAR文件,接下來就需要配置想要與Zipkin進行通信的每一項服務。這項任務可以通過設置一個Spring屬性spring.zipkin.baseUrl來完成,該屬性定義了用於與Zipkin通信的URL,它設置在每個服務的application.yml屬性文件中。
注意
spring.zipkin.baseUrl也可以作為Spring Cloud Config中的屬性進行外部化。
在每個服務的application.yml文件中,將該值設置為
http://localhost:9411。但是,在運行時,我使用在每個服務的Docker配置文件(docker/common/docker-compose.yml)上傳遞的ZIPKIN_URI(
http://zipkin:9411)變量來覆蓋這個值。
Zipkin、RabbitMQ與Kafka
Zipkin確實有能力通過RabbitMQ或Kafka將其跟蹤數據發送到Zipkin服務器。從功能的角度來看,不管使用HTTP、RabbitMQ還是Kafka,Zipkin的行為沒有任何差異。通過使用HTTP跟蹤,Zipkin使用異步線程發送性能數據。另外,使用RabbitMQ或Kafka來收集跟蹤數據的主要優勢是,如果Zipkin服務器關閉,任何發送給Zipkin的跟蹤信息都將“排隊”,直到Zipkin能夠收集到數據。
Spring Cloud Sleuth通過RabbitMQ和Kafka向Zipkin發送數據的配置在Spring Cloud Sleuth文檔中有介紹,因此本章將不再贅述。
9.3.3 安裝和配置Zipkin服務器
要使用Zipkin,首先需要按照本書多次所做的那樣建立一個Spring Boot項目(本章的項目名為 zipkinsvr)。接下來,需要向zipkinsvr/pom.xml文件添加兩個JAR依賴項。代碼清單9-4展示了這兩個JAR依賴項。
代碼清單9-4 Zipkin服務所需的JAR依賴項
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId> ⇽--- 這個依賴項包含用於創建Zipkin服務器所需的核心類
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId> ⇽--- 這個依賴項包含用於運行Zipkin服務器的UI部分所需的核心類 </dependency>
選擇@EnableZipkinServer還是@EnableZipkinStreamServer
關於上述JAR依賴項,有一件事需要注意,那就是它們不是基於Spring Cloud的依賴項。雖然Zipkin是一個基於Spring Boot的項目,但是@EnableZipkinServer並不是一個Spring Cloud注解,它是Zipkin項目的一部分。這通常會讓Spring Cloud Sleuth和Zipkin的新手混淆,因為Spring Cloud團隊確實編寫了@EnableZipkinStreamServer注解作為Spring Cloud Sleuth的一部分,它簡化了Zipkin與RabbitMQ和Kafka的使用。
我選擇使用@EnableZipkinServer是因為對本章來說它創建簡單。使用@EnableZipkinStreamServer需要創建和配置正在跟蹤的服務以發布消息到RabbitMQ或Kafka,此外,還需要設置和配置Zipkin服務器來監聽RabbitMQ或Kafka,以此來跟蹤數據。@EnableZipkinStreamServer注解的優點是,即使Zipkin服務器不可用,也可以繼續收集跟蹤數據。這是因為跟蹤消息將在消息隊列中累積跟蹤數據,直到Zipkin服務器可用於處理消息記錄。如果使用了@EnableZipkinServer注解,而Zipkin服務器不可用,那么服務發送給Zipkin的跟蹤數據將會丟失。
在定義完JAR依賴項之后,現在需要將@EnableZipkinServer注解添加到Zipkin服務引導類中。這個類位於zipkinsvr/src/main/java/com/thoughtmechanix/zipkinsvr/ZipkinServerApplication.java中。代碼清單9-5展示了引導類的代碼。
代碼清單9-5 構建Zipkin服務器引導類
package com.thoughtmechanix.zipkinsvr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import zipkin.server.EnableZipkinServer;
⇽--- @EnableZipkinServer 允許快速啟動Zipkin作為Spring Boot項目
@SpringBootApplication
@EnableZipkinServer
public class ZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinServerApplication.class, args);
}
}
在代碼清單9-5中要注意的關鍵點是@EnableZipkinServer注解的使用。這個注解能夠啟動這個Spring Boot服務作為一個Zipkin服務器。此時,讀者可以構建、編譯和啟動Zipkin服務器,作為本章的Docker容器之一。
運行Zipkin服務器只需要很少的配置。在運行Zipkin服務器時,唯一需要配置的東西,就是Zipkin存儲來自服務的跟蹤數據的后端數據存儲。Zipkin支持4種不同的后端數據存儲。這些數據存儲是:
(1)內存數據;
(2)MySQL;
(3)Cassandra;
(4)Elasticsearch。
在默認情況下,Zipkin使用內存數據存儲來存儲跟蹤數據。Zipkin團隊建議不要在生產系統中使用內存數據庫。內存數據庫只能容納有限的數據,並且在Zipkin服務器關閉或丟失時,數據就會丟失。
注意
對於本書來講,我們將使用Zipkin的內存數據存儲。配置Zipkin中使用的各個數據存儲超出了本書的范圍,但是,如果讀者對這個主題感興趣,可以在Zipkin GitHub存儲庫中查閱更多信息。
9.3.4 設置跟蹤級別
到目前為止,我們已經配置了要與Zipkin服務器通信的客戶端,並且已經配置完Zipkin服務器准備運行。在開始使用Zipkin之前,我們還需要再做一件事情,那就是定義每個服務應該向Zipkin寫入數據的頻率。
在默認情況下,Zipkin只會將所有事務的10%寫入Zipkin服務器。可以通過在每一個向Zipkin發送數據的服務上設置一個Spring屬性來控制事務采樣。這個屬性叫spring.sleuth.sampler.percentage,它的值介於0和1之間。
值為0表示Spring Cloud Sleuth不會發送任何事務數據。
值為0.5表示Spring Cloud Sleuth將發送所有事務的50%。
對於本章來講,我們將為所有服務發送跟蹤信息。要做到這一點,我們可以設置spring.sleuth.sampler.percentage的值,也可以使用AlwaysSampler替換Spring Cloud Sleuth中使用的默認Sampler類。AlwaysSampler可以作為Spring Bean注入應用程序中。例如,許可證服務在licensing-service/src/main/java/com/thoughtmechanix/licenses/Application.java 中將AlwaysSampler定義為Spring Bean。
@Bean
public Sampler defaultSampler() { return new AlwaysSampler();}
Zuul服務、許可證服務和組織服務都定義了AlwaysSampler,因此在本章中,所有的事務都會被Zipkin跟蹤。
spring cloud zipkin elk