案例代碼:https://github.com/q279583842q/springcloud-e-book
一、Sleuth介紹
為什么要使用微服務跟蹤?它解決了什么問題?
1.微服務的現狀?
微服務的現狀
隨着業務的發展,單體架構變為微服務架構,並且系統規模也變得越來越大,各微服務間的調用關系也變得越來越復雜。
多服務協同工作
在微服務的應用中,一個由客戶端發起的請求在后端系統中會經過多個不同的微服務調用來協同產生最后的請求結果
復雜的調用鏈條容易出錯
在復雜的微服務架構系統中,幾乎每一個前端請求都會形成一個復雜的分布式服務調用鏈路,在每條鏈路中任何一個依賴服務出現延遲超時或者錯誤都有可能引起整個請求最后的失敗
例如:
在微服務系統中,一個來自用戶的請求,請求先達到前端A(如前端界面)然后通過遠程調用,到達系統中間件B,C(負載均衡,網關等),最后達到后端服務D,E,后端經過一系列的業務邏輯計算最后將數據返回給用戶,對於這樣一個請求,經歷了這么多個服務,怎么樣將它的請求過程的數據記錄下來呢?這就需要用到服務鏈路追蹤
2.微服務跟蹤解決了什么問題?
微服務跟蹤(sleuth)其實是一個工具,它在整個分布式系統中能跟蹤一個用戶請求的過程(包括數據采集,數據傳輸,數據存儲,數據分析,數據可視化),捕獲這些跟蹤數據,就能構建微服務的整個調用鏈的視圖,這是調試和監控微服務的關鍵工具。
SpringCloudSleuth有4個特點
特點 | 說明 |
---|---|
提供鏈路追蹤 | 通過sleuth可以很清楚的看出一個請求經過了哪些服務, 可以方便的理清服務局的調用關系 |
性能分析 | 通過sleuth可以很方便的看出每個采集請求的耗時, 分析出哪些服務調用比較耗時,當服務調用的耗時 隨着請求量的增大而增大時,也可以對服務的擴容提 供一定的提醒作用 |
數據分析 優化鏈路 |
對於頻繁地調用一個服務,或者並行地調用等, 可以針對業務做一些優化措施 |
可視化 | 對於程序未捕獲的異常,可以在zipkpin界面上看到 |
二、Sleuth案例
我們通過一個簡單的微服務調用案例來演示下Sleuth是怎么跟蹤請求調用的,案例結構圖如下:
1.創建sleuth-product-service服務
1.1 創建服務
1.2 創建pojo
此處的Product類以及相關代碼在GitHub上
1.3 創建service接口
@RequestMapping("/product")
public interface ProductService {
@RequestMapping(value="findAll",method=RequestMethod.GET)
public List<Product> findAll();
}
2.創建sleuth-product-provider服務
2.1 創建項目
2.2 pom文件
注意添加sleuth的依賴
<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>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.bobo</groupId>
<artifactId>sleuth-product-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.bobo</groupId>
<artifactId>sleuth-product-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</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>
2.3 配置文件
沒有特殊的
spring.application.name=sleuth-product
server.port=9001
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u5730\u5740\uFF0C\u6307\u5411\u53E6\u4E00\u4E2A\u6CE8\u518C\u4E2D\u5FC3
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/
#--------------db----------------
mybatis.type-aliases-package=com.book.product.pojo
mybatis.mapper-locations=classpath:com/bobo/product/mapper/*.xml
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/book-product?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=123456
注意添加日志配置文件,日志級別設置為debug
2.4 業務代碼
業務代碼提供了對商品數據的查詢。
3.創建sleuth-consumer服務
3.1 創建項目
3.2 pom文件
統一注意添加sleuth的依賴
<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>1.5.13.RELEASE</version>
</parent>
<groupId>com.bobo</groupId>
<artifactId>sleuth-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 添加Feign坐標 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- 添加e-book-product-service坐標 -->
<dependency>
<groupId>com.bobo</groupId>
<artifactId>sleuth-product-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3 配置文件
沒有特殊的配置
spring.application.name=e-book-consumer
server.port=9010
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u5730\u5740\uFF0C\u6307\u5411\u53E6\u4E00\u4E2A\u6CE8\u518C\u4E2D\u5FC3
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/
3.4 業務代碼
通過Feign實現對商品服務的調用,具體代碼見GitHub,地址在頭部
4.服務跟蹤
先啟動product服務,然后啟動consumer服務,訪問:http://localhost:9010/find
請求訪問成功,注意查看控制台信息
consumer的控制器
product的控制台信息
5.Sleuth 日志分析
Created new Feign span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable:false]
# 調用 product服務
2019-06-30 09:43:24.022 [http-nio-9010-exec-8] DEBUG o.s.c.s.i.web.client.feign.TraceFeignClient - The modified request equals GET http://localhost:9001/product/findAll HTTP/1.1
X-B3-ParentSpanId: cbe97e67ce162943
X-B3-Sampled: 0
X-B3-TraceId: cbe97e67ce162943
X-Span-Name: http:/product/findAll
X-B3-SpanId: bb1798f7a7c9c142
# product中的日志輸出
## product 被調用
[findAll] to a span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable:false]
Adding a class tag with value [ProductController] to a span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable:false]
## 調用數據庫操作
org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@42858a0e] was not registered for synchronization because synchronization is not active
o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
o.m.spring.transaction.SpringManagedTransaction - JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@7981208d]]] will not be managed by Spring
com.bobo.mapper.ProductMapper.selectByExample - ==> Preparing: select id, name, status, price, deleted, create_time, update_time from product
com.bobo.mapper.ProductMapper.selectByExample - ==> Parameters:
com.bobo.mapper.ProductMapper.selectByExample - <== Total: 3
## 結束請求
o.s.cloud.sleuth.instrument.web.TraceFilter - Closing the span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable:false] since the response was successful
# consumer 中調用服務結束
Closing Feign span and logging CR [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable:false]
Closing Feign span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable:false]
如上,通過日志我們可以看出服務調用的相關過程
字段 | 描述 |
---|---|
trace | 從客戶發起請求(request)抵達被追蹤系統的邊界開始,到被追蹤系統向客戶返回響應(response)為止的整個過程 |
span | 每個trace中會調用若干個服務,為了記錄調用了哪些服務,以及每次調用的消耗時間等信息,在每次調用服務時,埋入一個調用記錄 |
X-B3-ParentSpanId | 標識當前工作單元所屬的上一個工作單元 |
X-B3-Sampled | 是否采樣,1表示需要被輸出,0表示不需要被輸出 |
X-B3-TraceId | 一條請求鏈路(trace)的唯一標識,必須值 |
X-Span-Name | 工作單元的名稱,例如: http:/product/findAll |
X-B3-SpanId | 一個工作單元(span)的唯一標識,必須值 |