使用sleuth實現(xiàn)微服務跟蹤

sleuth原理圖.png

在微服務架構中,眾多的微服務之間互相調用,如何清晰地記錄服務的調用鏈路是一個需要解決的問題。同時,由于各種原因,跨進程的服務調用失敗時,運維人員希望能夠通過查看日志和查看服務之間的調用關系來定位問題,而Spring cloud sleuth組件正是為了解決微服務跟蹤的組件。

sleuth的原理介紹可以參考這篇文章: 服務鏈路追蹤(Spring Cloud Sleuth)

本文主要講解sleuth的兩方面用法

  • sleuth+elk 結合,聚合微服務日志
  • sleuth+ zipkin結合,顯示文件調用鏈路

本文代碼參考hello+world+helloworldh+helloworldfeign+track這5個項目

sleuth+elk聚合日志

sleuth配置

  • 在微服務項目引入下列依賴
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
  • 配置文件application.yml增加
logging:
  level:
    root: INFO
    org.springframework.web.servlet.DispatcherServlet: DEBUG
    org.springframework.cloud.sleuth: DEBUG

  • 依次啟動hello項目helloworld項目,在瀏覽器輸入http://localhost:8020/message后兩個項目的控制臺輸出如下日志
helloworld日志
hello 日志.png

其中a7c81616d25c1a88是TraceId,后面跟著的是SpanId,依次調用有一個全局的TraceId,將調用鏈路串起來。

查看日志文件并不是一個很好的方法,當微服務越來越多日志文件也會越來越多,通過ELK可以將日志聚合,并進行可視化展示和全文檢索。

sleuth配合elk使用

ELK是一款日志分析系統(tǒng),它是Logstash+ElasticSearch+Kibana的技術組合,它可以通過logstash收集各個微服務日志,并通過Kibana進行可視化展示,而且還可以對大量日志信息通過ElasticSearch進行全文檢索。

ELK.png

操作步驟:

區(qū)別是在啟動logstash時,指定了日志來源路徑

/opt/logstash/bin/logstash -e 
'input { file { codec => json path => "/opt/build/*.json" } } 
output { elasticsearch { hosts => ["localhost"] } }'
  • 項目添加依賴
      <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>4.9</version>
        </dependency>
  • 在src/java/resources目錄下新建logback-spring.xml,配置如下內容
<?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"/>

    <property name="LOG_FILE"
              value="${BUILD_FOLDER:-build}/${springAppName}"/>

    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%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 name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>


    <!-- 按照每天生成日志文件 -->
    <appender name="filelog"  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>
            <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符-->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>


    <!-- 使用json格式保存日志文件 -->
    <appender name="jsonlog"  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>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="console"/>
        <appender-ref ref="jsonlog"/>
        <appender-ref ref="filelog"/>
    </root>


</configuration>

因為上面的日志文件用到spring.application.name,所以需要項目名稱的配置挪到bootstrap.yml。

  • 測試結果,在瀏覽器輸入http://localhost:8020/message發(fā)起幾次調用后,打開http://localhost:5601后看到上述的Kibana頁面,說明可以正常使用ELK查詢,分析跟蹤日志。

sleuth 結合zipkin

通過查看日志分析微服務的調用鏈路并不是一個很直觀的方案,結合zipkin可以很直觀地顯示微服務之間的調用關系。

trace列表.png
trace明細.png
服務依賴關系.png

通過zipkin可以將調用鏈路可視化顯示。
下面講解配置步驟:

服務端zipkin-server配置

  • 新建項目track,并引入依賴
    <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
     </dependency>
  • 啟動類添加@EnableDiscoveryClient@EnableZipkinServer注解
  • 配置文件application.yml
spring:
  application:
    name: sleuth-server
server:
  port: 9411

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
      instanceId: ${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port}

以上服務端就搭建好了

客戶端整合zipkin步驟

  • 客戶端添加依賴
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>  
  • 配置文件添加
spring:
  zipkin:
    base-url: http://127.0.0.1:9411
  sleuth:
    sampler:
      percentage: 1.0

指定了zipkin server的地址,下面制定需采樣的百分比,默認為0.1,即10%,這里配置1,是記錄全部的sleuth信息,是為了收集到更多的數據(僅供測試用)。在分布式系統(tǒng)中,過于頻繁的采樣會影響系統(tǒng)性能,所以這里配置需要采用一個合適的值。

zipkin改進

在這里對zipkin進行改進,主要包含兩方面

  • 通過消息中間件收集sleuth數據
  • 持久化sleuth數據

1、通過消息中間件收集sleuth數據
通過消息中間件可以將zipkin server和微服務解耦,微服務無需知道zipkin server地址,只需將sleuth數據傳入消息中間件。同時,也可以解決zipkin server與微服務網絡不通情況。

改造服務端

  • 修改zipkin server(trace項目)配置
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
        </dependency>

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

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

    <!--    <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
        </dependency>-->
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
        </dependency>
  • 配置文件application.yml增加
  rabbitmq:
    host: localhost
    port: 5673
    username: guest
    password: guest

這是sleuth數據來源

  • 啟動類@EnableZipkinServer改為@EnableZipkinStreamServe
    以上服務端改造完畢,下面改造客戶端(以helloworld-feign項目為例

改造客戶端
helloworldfeign項目為例

  • 修改依賴
  <!-- 使用消息中間件后,不再直接和zipkin server-->
       <!-- <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>-->

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

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
        </dependency>
  • 配置文件增加
spring:
  rabbitmq:
    host: localhost
    port: 5673
    username: guest
    password: guest

并刪除下面指向zipkin server的配置

spring:
  zipkin:
    base-url: http://127.0.0.1:9411

這樣就完成了客戶端的配置,依次啟動trackhelloworldfeign項目,通過http://localhost:8030/message調用其他服務后,在zipkin server 成功獲取了helloworldfeign的sleuth數據。

在以上的過程中,只要重啟zipkin server,發(fā)現(xiàn)之前的數據丟失。這是因為zipkin server獲取的數據是放在內存的,我們可以獲取的服務追蹤數據放入到ElasticSearch

2、持久化sleuth數據

  • 修改依賴

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

        <!-- 持久化到ElasticSearch-->
        <!--<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>-->
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
            <version>1.29.2</version>
        </dependency>


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

           <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
        </dependency>
  • 配置文件增加
zipkin:
  storage:
    type: elasticsearch
    elasticsearch:
      cluster: elasticsearch
      hosts: http://localhost:9200
      index: zipkin
      index-shards: 5
      index-replicas: 1

再次啟動track項目后,可以將數據持久化到elasticsearch。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 普元推出DevOps系列課程,5分鐘秒懂一個知識點,戳“閱讀原文”充電5分鐘,掌握黑科技。 轉載本文需注明出處:微...
    72a1f772fe47閱讀 4,634評論 0 0
  • 從今起,本座名約白蓮教主,小名啊白,小白,全面招收教徒,現(xiàn)已收貨護法一枚
    不如懷念9527閱讀 975評論 0 0
  • 暑假回了一趟外婆家,正值酷暑,那炙熱的陽光照到人身上,熱得人快要窒息似的。 那天下午,外公和舅舅突然說要搬柴,我心...
    靈風Alex閱讀 432評論 0 0
  • 前不久我在網上看到一句話: " 愛情對生命的意義是帶來蛻變,每一段戀情、每一個戀人,帶來關鍵性的蛻變契機。" 我一...
    L_7b26閱讀 216評論 0 0

友情鏈接更多精彩內容