SpringCloud之分散式服務跟蹤Spring Cloud Sleuth例項
一、簡介
隨著業務的發展,系統規模也會變得越來越大,各微服務間的呼叫關係也變得越來越錯綜複雜。通常一個由客戶端發起的請求在後端系統中會經過多個不同的微服務呼叫來協同產生最後的請求結果,在複雜的微服務架構系統中,幾乎每一個前端請求都會形成一條複雜的分散式服務呼叫鏈路,在每條鏈路中任何一個依賴服務出現延遲過高或錯誤的時候都有可能引起請求最後的失敗。這時候,對於每個請求,全鏈路呼叫的跟蹤就變得越來越重要,通過實現對請求呼叫的跟蹤可以幫助我們快速發現錯誤根源以及監控分析每條請求鏈路上的效能瓶頸等。
針對上面所述的分散式服務跟蹤問題,Spring Cloud Sleuth提供了 一套完整的解決方案。
二、Zipkin
Zipkin是Twitter的一個開源專案,它基於 Google Dapper 實現。我們可以使用它來收集各個伺服器上請求鏈路的跟蹤資料,並通過它提供的REST API介面來輔助查詢跟蹤資料以實現對分散式系統的監控程式,從而及時發現系統中出現的延遲升高問題並找出系統性能瓶頸的根源。除了面向開發的API介面之外,它還提供了方便的UI元件來幫助我們直觀地搜尋跟蹤資訊和分析請求鏈路明細,比如可以查詢某段時間內各使用者請求的處理時間等。
下圖展示了Zipkin的基礎架構, 它主要由4個核心元件構成。
- Collector:收集器元件,它主要處理從外部系統傳送過來的跟蹤資訊,將這些資訊轉換為Zipkin內部處理的Span格式,以支待後續的儲存、分析、展示等功能。
- Storage:儲存元件,它主要處理收集器接收到的跟蹤資訊,預設會將這些資訊儲存在記憶體中。我們也可以修改此儲存策略, 通過使用其他儲存元件將跟蹤資訊儲存到資料庫中。
- RESTful API: API元件,它主要用來提供外部訪問介面。比如給客戶端展示跟蹤資訊,或是外接系統訪問以實現監控等。
- Web UI: UI元件,基於API元件實現的上層應用。通過UI元件,使用者可以方便而又直觀地查詢和分析跟蹤資訊。
三、 搭建Zipkin Server
(1)新建一個SpringBoot專案,命名無要求;
(2)pom.xml,新增zipkin依賴
(3)application.yml<dependencies> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> </dependency> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</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>
spring:
application:
name: zipkin-server
server:
port: 5595
(4)入口類
@EnableZipkinServer
@SpringBootApplication
public class SpringcloudsleuthzipkinApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudsleuthzipkinApplication.class, args);
}
}
(5)建立完上述工程之後,我們將其啟動起來,並訪問http: I /localhost:5595/, 可以看到如下圖所示的Zipkin管理頁面:
四、搭建trace1-client
(1)建立一個SpringBoot專案,命名無要求;(2)pom.xml
<?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>
<groupId>com.example</groupId>
<artifactId>springcloudsleuthtrace1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloudsleuthtrace1</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Edgware.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</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>
</project>
(3)application.yml
server:
port: 5596
spring:
zipkin:
base-url: http://localhost:5595
application:
name: trace1-client
(4)入口類@RestController
@EnableDiscoveryClient
@SpringBootApplication
public class Springcloudsleuthtrace1Application {
private static final Logger log = LoggerFactory.getLogger(Springcloudsleuthtrace1Application.class);
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
@RequestMapping(value = "/trace1", method = RequestMethod.GET)
public String trace() {
log.info("<<<<<-call trace1->>>>>");
return restTemplate().getForEntity("http://localhost:5597/trace2", String.class).getBody();
}
public static void main(String[] args) {
SpringApplication.run(Springcloudsleuthtrace1Application.class, args);
}
}
五、搭建trace2-client
(1)建立一個SpringBoot專案,命名無要求;(2)pom.xml
<?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>
<groupId>com.example</groupId>
<artifactId>springcloudsleuthtrace2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloudsleuthtrace2</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Edgware.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</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>
</project>
(3)application.yml
server:
port: 5597
spring:
zipkin:
base-url: http://localhost:5595
application:
name: trace2-client
(4)入口類
@RestController
@EnableDiscoveryClient
@SpringBootApplication
public class Springcloudsleuthtrace2Application {
private static final Logger log = LoggerFactory.getLogger(Springcloudsleuthtrace2Application.class);
@RequestMapping(value = "/trace2", method = RequestMethod.GET)
public String trace(){
log.info("=====<<<call trace2>>>=====");
return "Trace";
}
public static void main(String[] args) {
SpringApplication.run(Springcloudsleuthtrace2Application.class, args);
}
}
六、測試
(1)分別啟動zipkin-server--埠5595;trace1-client--埠5596;trace2-client--埠5597;(2)訪問http://localhost:5596/trace1
得到的結果是http://localhost:5597/trace2的內容,程式通過:
restTemplate().getForEntity("http://localhost:5597/trace2", String.class).getBody();
使用RestTemplate呼叫 trace2應用的介面。
(3)開啟zipkin管理介面--依賴分析
(4)開啟zipkin管理介面--查詢呼叫鏈
(6)點選上圖紅框
- 通過以上的步驟,可以看到具體服務相互呼叫的資料
參考資料《Spring Cloud微服務實戰》