1. 程式人生 > >Spring Cloud應用進行服務追蹤分析(Zipkin和spring cloud Sleuth)

Spring Cloud應用進行服務追蹤分析(Zipkin和spring cloud Sleuth)

參考文章二:(我參考的這個)

最近在學習spring cloud構建微服務,很多大牛都提供很多入門的例子幫助我們學習,對於我們這種英語不好的碼農來說,效率著實提高不少。這兩天學習到追蹤微服務rest服務呼叫鏈路的問題,接觸到zipkin,而spring cloud也提供了spring-cloud-sleuth來方便整合zipkin實現。

在網路上找了好多文章,不過發現版本引入的maven依賴包,配置的引數都不完全相同。可能是因為版本更新太快 的原因,部分配置已經取消掉了。光看不動手始終是不夠的,於是自己根據其他大神的部落格以及github上作者的示例來自己練手試試。

我們準備了三個必要的程式來做測試,分別是
1、zipkin-server
負責資料收集以及資訊展示功能。
2、provider
負責微服務的生產者,對外提供 “

http://127.0.0.1:10001/add/被加數/加數” 的rest地址來完成一個簡單的兩整數相加的功能。
3、consumer
負責微服務的呼叫,對外提供 "http://127.0.0.1:10002/test/add/被加數/加數" 的rest地址,當訪問此地址時,使用feign方式呼叫provider的rest服務地址。得到計算結果後,顯示在介面上。

三個程式功能非常簡單,接下來我們看看每個程式的具體程式碼和配置。為了方便我們對三個模組開發,我們在父POM檔案中添加了spring-boot和spring-cloud的依賴,避免子模組中需要寫版本號

<parent>
 <groupId>org.springframework.boot</groupId
>
<artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId
>
<version>Dalston.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

接下來我們看看三個程式中的相關配置

一、zipkin-server

首先,我們新增maven依賴配置

<dependencies>
 <!--使用@EnableZipkinServer註解方式只需要依賴如下兩個包-->
 <dependency>
  <groupId>io.zipkin.java</groupId>
  <artifactId>zipkin-server</artifactId>
 </dependency>
 <dependency>
  <groupId>io.zipkin.java</groupId>
  <artifactId>zipkin-autoconfigure-ui</artifactId>
  <scope>runtime</scope>
 </dependency>
 <!--儲存到資料庫需要如下依賴-->
 <dependency>
  <groupId>io.zipkin.java</groupId>
  <artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
 </dependency>
 <dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
 </dependency>
 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jdbc</artifactId>
 </dependency>

線下測試環境中,我們可以將資料儲存到記憶體中,但是生產環境還是需要將資料持久化中。原生支援了很多產品,例如ES、資料庫等,本例中我們採用持久化到mysql中的方式來演示。

我們寫一個啟動類ZipkinServer,程式碼非常簡單,如下

@SpringBootApplication
@EnableZipkinServer //啟動ZipkinServer段
public class ZipkinServer {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinServer.class, args);
    }
}

接下來我們配置application.properties配置檔案

server.port=9411
spring.application.name=zipkin-server
#zipkin資料儲存到資料庫中需要進行如下配置
#表示當前程式不使用sleuth
spring.sleuth.enabled=false
#表示zipkin資料儲存方式是mysql
zipkin.storage.type=mysql
#資料庫指令碼建立地址,當有多個是可使用[x]表示集合第幾個元素
spring.datasource.schema[0]=classpath:/zipkin.sql
#spring boot資料來源配置
spring.datasource.url=jdbc:mysql://localhost:3306/zipkin?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.initialize=true
spring.datasource.continue-on-error=true

從以上配置可以看到我們建立了一個 zipkin的資料庫,初始化指令碼為classpath下的zipkin.sql的sql檔案。具體內容見附件。

啟動後 無異常輸出,這樣我們的zipkin-server程式就OK了

screenshot

二、provider和consumer

provider和consumer兩個程式,與其他基礎程式碼我們就不多講了(相信學些到這一步的童鞋,都已經對spring cloud建立微服務以上手了),兩個程式在spring-cloud-sleuth相關的配置都是一樣。
首先,我們要在二者的POM檔案中新增依賴,引入zipkin客戶端自動配置相關依賴

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

其次,在配置檔案application中,我們加入zipkin-server收集資訊的地址

#配置zipKin Server的地址
spring.zipkin.base-url=http://127.0.0.1:9411

這樣我們的兩個微服務就配置好了(注意這裡我們並不會再說明如何寫rest介面和使用feign呼叫rest介面)

三、測試

啟動我們的三個程式。然後訪問zipkin-server程式的UI介面地址http://127.0.0.1:9411,可以看到如下的效果
screenshot
其中Span Name選項為灰色不可選,說明目前沒有資料,我們檢視資料庫也可以看到沒有任何資料資訊。接下來我們訪問consumer提供的訪問地址 “http://127.0.0.1:10001/add/被加數/加數” 重新整理幾次之後,我們再次重新整理我們的zipkin介面,可以看到Span Name已經可以選擇了。
screenshot
點選Find Traces按鈕,我們可以看到呼叫的鏈路和耗時情況,點選Dependencies,我們可以看到provider和consumer的呼叫圖
screenshot

OK,我們的簡單實用spring-cloud-sleuth+zipkin的例子就完成了。

注意:

測試時請將consumer訪問地址中的“被加數”和“加數”替換為兩個整數。

四、拓展

在測試的過程中我們會發現,有時候,程式剛剛啟動後,重新整理幾次,並不能看到任何資料,原因就是我們的spring-cloud-sleuth收集資訊是有一定的比率的,預設的取樣率是0.1,配置此值的方式在配置檔案中增加spring.sleuth.sampler.percentage引數配置(如果不配置預設0.1),如果我們調大此值為1,可以看到資訊收集就更及時。但是當這樣調整後,我們會發現我們的rest介面呼叫速度比0.1的情況下慢了很多,即時在0.1的取樣率下,我們多次重新整理consumer的介面,也會出現如下情況
screenshot
紅色框中上下兩個資料是兩次耗時資訊,可以看到相差非常大,如果取消spring-cloud-sleuth後我們再測試,會發現並沒有這種情況,可以看到這種方式追蹤服務呼叫鏈路會給我們業務程式效能帶來一定的影響。

其實,我們仔細想想也可以總結出這種方式的幾種缺陷
缺陷1:zipkin客戶端向zipkin-server程式傳送資料使用的是http的方式通訊,每次傳送的時候涉及到連線和傳送過程。
缺陷2:當我們的zipkin-server程式關閉或者重啟過程中,因為客戶端收集資訊的傳送採用http的方式會被丟失。

針對以上兩個明顯的缺陷,改進的辦法是
1、通訊採用socket或者其他效率更高的通訊方式。
2、客戶端資料的傳送儘量減少業務執行緒的時間消耗,採用非同步等方式傳送收集資訊。
3、客戶端與zipkin-server之間增加快取類的中介軟體,例如redis、MQ等,在zipkin-server程式掛掉或重啟過程中,客戶端依舊可以正常的傳送自己收集的資訊。

相信採用以上三種方式會很大的提高我們的效率和可靠性。其實spring-cloud以及為我們提供採用MQ或redis等其他的採用socket方式通訊,利用訊息中介軟體或資料庫快取的實現方式。下一次我們再來測試spring-cloud-sleuth-zipkin-stream方式的實現。

參考文件:

參考文章三:(監聽訊息的方式,我參考的這個)


在上一節《spring-cloud-sleuth+zipkin追蹤服務實現(一)》中,我們使用zipkin-server、provider、consumer三個程式實現了使用http方式進行通訊,資料持久化到資料庫中的服務呼叫鏈路追蹤實現。針對其中存在的影響效能和可能丟失資料的缺陷,在這一節我們使用spring-cloud的為我們提供的實現的方式來測試這種情況。

我們還是使用之前上一節中的三個程式做修改,方便大家看到對比不同點。

一、zipkin-server

要將http方式改為通過MQ通訊,我們要將依賴的原來依賴的io.zipkin.java:zipkin-server換成spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit,並且移除zipkin-autoconfigure-storage-mysql,因為spring-cloud-sleuth-zipkin-stream會自動為我們引入,全部maven依賴如下:

        <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <!--zipkin依賴-->
        <!--此依賴會自動引入spring-cloud-sleuth-stream並且引入zipkin的依賴包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--儲存到資料庫需要如下依賴-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>

新增以上maven依賴後,我們將啟動類ZipkinServer中@EnableZipkinServer註解替換成@EnableZipkinStreamServer

@SpringBootApplication
@EnableDiscoveryClient //註冊到eureka
@EnableZipkinStreamServer //使用Stream方式啟動ZipkinServer
public class ZipkinServer {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinServer.class, args);
    }
}

點選@EnableZipkinStreamServer註解的原始碼我們可以看到它也引入了@EnableZipkinServer註解,同時還建立了一個rabbit-mq的訊息佇列監聽器。
screenshot
以方便接收從訊息客戶端收集發過來的mq訊息。由於使用了訊息中介軟體rabbit-mq,所以我們還需要在配置檔案中配置我們的MQ連線配置

#rabbitmq配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

為了避免http通訊的干擾,我們將原來的監聽埠有9411更改為9412,啟動程式,未報錯且能夠看到rabbit連線日誌,說明程式啟動成功。

二、provider和consumer
與上一節中的配置一樣,客戶端的配置也非常簡單,maven依賴只需要將原來的spring-cloud-starter-zipkin替換為如下兩個依賴即可

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

此外,在配置檔案中也加上連線MQ的配置

#rabbitmq配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

在第一節中,客戶端連線zipkin-server是使用的配置
spring.zipkin.base-url=http://127.0.0.1:9411, 由於不再使用這種方式,我們將它取消掉。同時,我們將資料庫中的資料也清空。

我們如上一節《spring-cloud-sleuth+zipkin追蹤服務實現(一)》中一樣,訪問consumer的外部http地址("http://127.0.0.1:10001/add/被加數/加數") 。然後我們訪問zipkin-server的地址“http://127.0.0.1:9412/” ,我們可以看到如下的效果,說明rabbit-mq方式通訊的sleuth功能已經生效了。
screenshot
我們多次訪問consumer的地址可以看到日誌中,請求的耗時時間不會再次出現突然耗時特長的情況。

為了體驗MQ通訊給我們帶來的資料不丟失的特點,我們將資料庫中的資料清空,然後重新整理zipkin-server的介面,可以看到不再有資料
screenshot

然後我們將zipkin-server程式想關閉,然後再多次訪問consumer的地址,之後,我們重啟zipkin-server程式,啟動成功後訪問UI介面
screenshot
很快看到Span Name選項有資料可以選擇了,同時資料庫中的記錄條數也不再是之前的0條了
screenshot

如此說明我們的zipkin重啟後,從MQ中成功獲取出了在關閉這段時間裡provider和consumer產生的資訊資料。這樣我們使用spring-cloud-sleuth-stream+zipkin方式的rest服務呼叫追蹤功能就OK了。

注意:
測試時請將consumer訪問地址中的“被加數”和“加數”替換為兩個整數。