天天看點

SpringCloud-鍊路追蹤sleuth

文章目錄

      • 版本說明
      • 簡介
      • 術語
    • Zipkin
    • 示例
      • 啟動zipkin
      • 依賴
      • 配置檔案
      • 驗證
    • 使用rabbitmq進行鍊路資料傳輸(可選)
    • 日志收集(可選)
      • Elasticsearch+Kibana+Logstash

在分布式系統中,鍊路将總是十分重要。

版本說明

元件 版本 說明
zipkin 2.12.9
rabbitmq 3.7.15
erl 10.4 rabbitmq依賴
elasticsearch 6.5.3 使用7.x會與zipkin沖突
kibana 6.5.3 使用7.x會與zipkin沖突
logstash 6.5.3 使用7.x會與zipkin沖突

簡介

Spring Cloud Sleuth 為服務之間調用提供鍊路追蹤。了解到一個服務請求經過了哪些服務,每個服務處理花費了多長。進而讓我們理清各微服務間的調用關系。

功能:

  • 耗時分析: 獲得每個采樣(鍊路追蹤可以不展示全部)請求的耗時;
  • 可視化錯誤: 對于程式未捕捉的異常,可以通過內建 Zipkin 服務界面上看到;
  • 鍊路優化: 對于調用比較頻繁的服務,可以針對這些服務實施一些優化措施。

術語

  • Span:基本工作單元,發送一個遠端排程任務就會産生一個Span,Span是用一個64位ID唯一辨別的,Trace是用另一個64位ID唯一辨別的。Span還包含了其他的資訊,例如摘要、時間戳事件、Span的ID以及程序ID。
  • Trace:由一系列Span組成的,呈樹狀結構。請求一個微服務系統的API接口,這個API接口需要調用多個微服務單元,調用每個微服務單元都會産生一個新的Span,所有由這個請求産生的Span組成了這個Trace。
  • Annotation:用于記錄一個事件,定義一個請求的開始和結束,如下:
    • cs (Client Sent):用戶端發送一個請求,描述Span的開始。
    • sr (Server Received):服務端獲得請求并準備開始處理它,如果将其sr減去cs時間戳,便可得到網絡傳輸的時間。
    • ss (Server Sent):服務端發送響應,該注解表明請求處理的完成(當請求傳回用戶端),用ss的時間戳減去sr時間戳,便可以得到伺服器請求的時間。
    • cr (Client Received):用戶端接收響應,此時Span結束,如果cr的時間戳減去cs時間戳,便可以得到整個請求所消耗的時間。

Zipkin

Zipkin是一種分布式鍊路追蹤系統。 收集鍊路中的資料,并且可以以界面的形式展現。

Zipkin UI還提供了一個依賴關系圖,顯示了每個應用程式通過的跟蹤請求數。

zipkin已經不再支援開發者自己開發zipkin server,而是以一個jar包啟動。

下載下傳jar包

curl -sSL https://zipkin.io/quickstart.sh | bash -s
           

或者https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec

或者pull docker鏡像

docker pull zipkin
           

示例

啟動zipkin

java -jar zipkin.jar
           

預設端口為9411

依賴

所有的服務相對于zipkin server 都是client,是以所有的服務都需要以下依賴

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

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

配置檔案

增加以下内容

spring:
  #鍊路追蹤
  sleuth:
    web:
      client:
        enabled: true
    # 采樣比例,預設是0.1,最大為1,表示采集資料的比例
    sampler:
      probability: 1.0
#zipkin的位址
  zipkin:
    base-url: http://localhost:9411/

           

驗證

代碼不需要任何改動。

確定啟動了consul,zipkin

在浏覽器中輸入

http://localhost:9411

調用服務,可以在浏覽器中搜尋服務,獲得鍊路追蹤後的詳細資訊;還可以觀察每一個服務的依賴關系。

SpringCloud-鍊路追蹤sleuth

使用rabbitmq進行鍊路資料傳輸(可選)

1 . 下載下傳,安裝,啟動rabbitmq;在浏覽器中輸入

http://localhost:15672

檢查是否成功

2 . 啟動zipkin

zipkin啟動需要讀取一些環境變量來配置自己。

屬性 環境變量 描述
zipkin.collector.rabbitmq.addressed RABBIT_ADDRESSES 用逗号分隔的 RabbitMQ 位址清單,例如localhost:5672,localhost:5673
zipkin.collector.rabbitmq.password RABBIT_PASSWORD 連接配接到 RabbitMQ 時使用的密碼,預設為 guest
zipkin.collector.rabbitmq.username RABBIT_USER 連接配接到 RabbitMQ 時使用的使用者名,預設為guest
zipkin.collector.rabbitmq.virtual-host RABBIT_VIRTUAL_HOST 使用的 RabbitMQ virtual host,預設為 /
zipkin.collector.rabbitmq.use-ssl RABBIT_USE_SSL 設定為true則用 SSL 的方式與 RabbitMQ 建立連結
zipkin.collector.rabbitmq.concurrency RABBIT_CONCURRENCY 并發消費者數量,預設為1
zipkin.collector.rabbitmq.connection-timeout RABBIT_CONNECTION_TIMEOUT 建立連接配接時的逾時時間,預設為 60000毫秒,即 1 分鐘
zipkin.collector.rabbitmq.queue RABBIT_QUEUE 從中擷取 span 資訊的隊列,預設為 zipkin

最好使用環境變量,在java指令中直接設定屬性值會失效

set RABBIT_ADDRESSES=localhost
set path=%path%;RABBIT_ADDRESSES
java -jar zipkin.jar
           

在浏覽器中輸入

http://localhost:9411/zipkin/

檢查是否成功

3 . 引入依賴

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
           

4 . 修改配置檔案

spring:
# 使用rabbitmq後去掉
#  zipkin:
#    base-url: http://localhost:9411/
  zipkin:
    sender:
      type: rabbit
  rabbitmq:
    host: localhost
    username: guest
    password: guest
    port: 5672

           

注釋 base-url,添加rabbitmq的配置

日志收集(可選)

Elasticsearch+Kibana+Logstash

Logstash(收集伺服器上的日志檔案) -->然後儲存到 ElasticSearch(搜尋引擎) -->Kibana提供友好的web界面(從ElasticSearch讀取資料進行展示)

1 .下載下傳Elasticsearch和Kibana,Logstash,解壓

2 .啟動

elasticsearch.bat

kibana.bat

3 .配置Logstash并啟動

在logstash安裝目錄/bin下建立檔案logstash.conf,内容如下

input {
  beats {
    port => 5044
  }
}

filter {
       # pattern matching logback pattern
       grok {
              match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}\s+---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
       }
}

output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    #index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
    index => "zipkin-%{+YYYY.MM.dd}"
	#user => "elastic"
    #password => "changeme"
  }
}

           

啟動logstash:

logstash -f logstash.conf

4 .添加依賴

<!--日志-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>4.11</version>
        </dependency>
           

5 .配置服務logback-spring.xml,以json格式将日志輸出到檔案,在項目目錄/bulid下

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    ​
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- Example for logging into the build folder of your project -->
    <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>​

    <!-- You can override this to have a custom pattern -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>

    <!-- Appender to log to console -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- Minimum logging level to be presented in the console logs-->
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- Appender to log to file -->​
    <appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>
    ​
    <!-- Appender to log to file in a JSON format -->
    <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}.json</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "trace": "%X{X-B3-TraceId:-}",
                        "span": "%X{X-B3-SpanId:-}",
                        "parent": "%X{X-B3-ParentSpanId:-}",
                        "exportable": "%X{X-Span-Export:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "rest": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>
    ​
    <root level="INFO">
        <appender-ref ref="console"/>
        <!-- uncomment this to have also JSON logs -->
        <appender-ref ref="logstash"/>
        <appender-ref ref="flatfile"/>s
    </root>
</configuration>
           

6 .啟動consul,rabbitmq,Elasticsearch,Kibana,各個服務

7 .啟動zipkin

set RABBIT_ADDRESSES=localhost
set STORAGE_TYPE=elasticsearch
set ES_HOSTS=http://localhost:9200
set ES_INDEX=zipkin
set path=%path%;RABBIT_ADDRESSES;STORAGE_TYPE;ES_HOSTS;ES_INDEX
java -jar zipkin.jar
           

8 .測試通路

http://localhost:9411/zipkin/

9 .将資料通過kibana展示

  • kibana預設端口是

    5601

    ,在浏覽器中輸入

    http://localhost:5601

  • 單擊“Management”按鈕,然後單擊“Add New”,添加一個index。ElasticSearch中寫傳入連結路資料的index配置為“zipkin”,那麼在界面填寫為“zipkin*”,單擊“Create”按鈕。
SpringCloud-鍊路追蹤sleuth
  • 點選Discover按鈕檢視資料
SpringCloud-鍊路追蹤sleuth