【SpringCloud Greenwich版本】第九章鏈路追蹤(Sleuth)
一、SpringCloud版本
本文介紹的Springboot版本為2.1.1.RELEASE,SpringCloud版本為Greenwich.RC1,JDK版本為1.8,整合環境為IntelliJ IDEA
二、Spring Cloud Sleuth介紹
Spring Cloud Sleuth為Spring Cloud實現分散式跟蹤解決方案。
微服務架構上通過業務來劃分服務的,通過REST呼叫,對外暴露的一個介面,可能需要很多個服務協同才能完成這個介面功能,如果鏈路上任何一個服務出現問題或者網路超時,都會形成導致介面呼叫失敗。隨著業務的不斷擴張,服務之間互相呼叫會越來越複雜,在專案中引入sleuth可以方便程式進行除錯。
sleuth中的一些術語
Spring Cloud Sleuth借用了Dapper的術語。
- Span:基本工作單元,例如,在一個新建的span中傳送一個RPC等同於傳送一個迴應請求給RPC,span通過一個64位ID唯一標識,trace以另一個64位ID表示,span還有其他資料資訊,比如摘要、時間戳事件、關鍵值註釋(tags)、span的ID、以及進度ID(通常是IP地址)
span在不斷的啟動和停止,同時記錄了時間資訊,當你建立了一個span,你必須在未來的某個時刻停止它。
通俗點理解Span相當於各個子系統的服務,註冊到Zipkin中,統一管理從而實現各服務之間的鏈路追蹤。也可以理解跟服務註冊中心Eureka類似
- 跟蹤:一系列spans組成的一個樹狀結構,例如,如果你正在跑一個分散式大資料工程,你可能需要建立一個trace。
- 註釋:用於及時記錄事件的存在。用於定義請求的開始和停止的一些核心註釋是:
- cs - Client Sent -客戶端發起一個請求,這個annotion描述了這個span的開始
- sr - Server Received -服務端獲得請求並準備開始處理它,如果將其sr減去cs時間戳便可得到網路延遲
- ss - Server Sent -註解表明請求處理的完成(當請求返回客戶端),如果ss減去sr時間戳便可得到服務端需要的處理請求時間
- cr - Client Received-表明span的結束,客戶端成功接收到服務端的回覆,如果cr減去cs時間戳便可得到客戶端從服務端獲取回覆的所有所需時間
注:本文分三部分搭建
第一步:搭建鏈路追蹤服務端(Zipkin服務端)
第二部:子系統配置鏈路追蹤
第三部:訪問測試
三、建立Sleuth服務
- 3.1建立Zipkin服務端
建立一個module,取名問cloudzipkin,手動匯入pom檔案,這裡沒有引用父pom檔案
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jthao</groupId>
<artifactId>cloudzipkin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloudzipkin</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RC1</spring-cloud.version>
</properties>
<dependencies>
<!--引入的zipkinServer依賴-->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
啟動類上增加@EnableZipkinServer註解,標識為zipkin服務端
package com.jthao.cloudzipkin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import zipkin.server.internal.EnableZipkinServer;
@EnableZipkinServer
@SpringBootApplication
public class CloudzipkinApplication {
public static void main(String[] args) {
SpringApplication.run(CloudzipkinApplication.class, args);
}
}
修改配置檔案
server.port=8201
spring.main.allow-bean-definition-overriding=true
management.metrics.web.server.auto-time-requests=false
通過瀏覽器訪問http://localhost:8201/zipkin/,稍後會詳細介紹這個頁面
- 3.2建立子系統
建立兩個module,取名為servicea和serviceb,選擇Cloud Tracing,再勾選上Zipkin Client,完成
建立完成的pom檔案,可以看到spring-cloud-starter-zipkin依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jthao</groupId>
<artifactId>servicea</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>servicea</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RC1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
servicea啟動類和配置檔案,埠分別為8202,8203。spring.zipkin.base-url為配置zipkin服務端地址
package com.jthao.servicea;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@SpringBootApplication
public class ServiceaApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceaApplication.class, args);
}
@Autowired
private RestTemplate restTemplate;
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@RequestMapping("/serviceAInfo")
public String serviceAInfo() {
System.out.println("serviceAInfo start");
return "serviceA 被呼叫了";
}
@RequestMapping("/getServiceB")
public String getServiceB() {
System.out.println("開始訪問serviceb");
return restTemplate.getForObject("http://localhost:8203/serviceBInfo", String.class);
}
}
server.port=8202
spring.application.name=servicea
spring.zipkin.base-url=http://localhost:8201
serviceb啟動類和配置檔案
package com.jthao.serviceb;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@SpringBootApplication
public class ServicebApplication {
public static void main(String[] args) {
SpringApplication.run(ServicebApplication.class, args);
}
@Autowired
private RestTemplate restTemplate;
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@RequestMapping("/serviceBInfo")
public String serviceBInfo() {
System.out.println("serviceBInfo start");
return "serviceB 被呼叫了";
}
@RequestMapping("/getServiceA")
public String getServiceA() {
System.out.println("開始訪問servicea");
return restTemplate.getForObject("http://localhost:8202/serviceAInfo", String.class);
}
}
server.port=8203
spring.application.name=serviceb
spring.zipkin.base-url=http://localhost:8201
通過瀏覽器分別訪問http://localhost:8202/getServiceB和http://localhost:8203/getServiceA
到這,zipkin服務端和兩個子系統鏈路追蹤均已搭建完成
- 3.3測試
這時我們在看zipkin服務端訪問頁面依賴分析,可以看到servicea和serviceb互相依賴呼叫(這裡只有serviea和serviceb互相呼叫後才可以看到)
查詢呼叫鏈中,可以看到Service name中有兩個子系統的註冊服務,類似於服務註冊中心,Span name可以查到各個服務的所有方法,下面的訪問情況藍色代表網路通暢,紅色代表訪問失敗