分佈式鏈路追蹤體驗-skywalking入門使用

背景

旁友,你的線上服務是不是偶爾來個超時,或者突然抖動一下,造成用戶一堆反饋投訴。然後你費了九牛二虎之力,查了一圈圈代碼和日誌才總算定位到問題原因了。或者公司內部有鏈路追蹤系統,雖然可以很輕鬆地通過監控判斷問題出現的原因,但是對其中的邏輯完全摸不着頭腦。只能上網搜索一番。

旁友,skywalking分佈式鏈路追蹤框架了解一下。

有的旁友會有疑惑,我的Spring Boot 就是一個單體應用么,不需要鏈路追蹤?有問題直接翻日誌就行了,但是即使是一個 Spring Boot 單體應用,也會和以下服務打交道:

  • 關係數據庫,例如說 MySQL、PostgreSQL 等等。
  • 緩存數據庫,例如說 Redis、Memcached 等等。
  • 外部三方服務,例如說微信公眾號、微信支付、支付寶支付、短訊平台等等

可見,僅僅一個 Spring Boot 單體應用,就已經涉及到分佈在不同進程中的服務了。此時,就非常有必要用上skywalking。例如說,線上某個 接口訪問非常慢,用SkyWalking 可以定位是MySQL 查詢比較慢呢,還是調用的第三方服務比較慢。

而在分佈式服務中,各個大廠內部系統成百上千的,鏈路關係更加複雜。比如你在外賣平台上的一個點擊請求可能跨了內部幾十個Java應用了,在這麼長的鏈路里去排查問題,沒有好使的工具怎麼行呢。如圖是當前分佈式系統的現狀,圖片來源:鷹眼下的淘寶分佈式調用跟蹤系統介紹

根據上圖,我們設想:

1.系統中有可能每天都在增加新服務或刪除舊服務,也可能進行升級,當系統出現錯誤,我們如何定位問題?

2.當用戶請求時,響應緩慢,怎麼定位問題?

3.服務可能由不同的編程語言開發,1、2 定位問題的方式,是否適合所有編程語言?

Skywalking框架

1.介紹

SkyWalking 是什麼?

官方網址 //skywalking.apache.org/

skywalking是一個優秀的國產開源框架,2015年由個人吳晟(華為開發者)開源 , 2017年加入Apache孵化器。短短兩年就被Apache收入麾下,實力可見一斑。

分佈式系統的應用程序性能監視工具,專為微服務、雲原生架構和基於容器(Docker、K8s、Mesos)架構而設計。

提供分佈式追蹤、服務網格遙測分析、度量聚合和可視化一體化解決方案。

代碼無侵入,通信方式採用GRPC,實現方式是java探針,支持告警,JVM監控,支持全局調用統計等等

skywalking的架構參考了谷歌的Dapper框架的論文,Dapper並沒有開源,只給了篇論文,感興趣但又不喜英文文檔的旁友可以看看論文的中文翻譯Dapper,大規模分佈式系統的跟蹤系統

整體架構如下:

  • Tracing Metrics Logging :負責從應用中,收集鏈路信息,發送給 SkyWalking OAP 服務器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 數據信息。Java應用通常使用SkyWalking Agent 收集數據
  • SkyWalking OAP :skywalking服務端(Transport layer,Receiver cluster,Aggregator cluster)負責接收 Agent 發送的 Tracing 數據信息,然後進行分析,存儲到外部存儲器( Storage ),最終提供查詢功能。
  • Storage option :Tracing 數據存儲。目前支持 ES、H2 多種存儲器。我們用ES存儲即可 。
  • GUI :負責提供可視化控台,查看鏈路等
  • Alarm:提供告警功能,這裡不展示講

2.Docker方式搭建Skywalking環境

為了快速搭建環境,避免各種系統、配置環境不同造成踩坑的情況。我們用docker直接創建ElasticSearch、Skywalking-OAP、Skywalking-UI以及ES的管理工具Kibana。這樣一套運行環境直接就能用了。話不多說,直接開干

整體架構如下:

用到的工具版本號如下表:

工具 版本號
ElasticSearch 7.14.2
Kibana 7.14.2
skywalking-oap-server 9.1.0
skywalking-ui 9.1.0

其中skywalking的docker-compos.yml運行腳本可以從官方的Github上獲取apache/skywalking/docker

腳本需要修改,直接參考我的就行,不懂的參數都有具體說明:

version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.14.2
    container_name: elasticsearch
    ports:
      - 9200:9200
      - 9300:9300
    environment:
      - "cluster.name=elasticsearch"
      - "bootstrap.memory_lock=true"
      - "ES_JAVA_OPTS=-Xms256m -Xmx512m"
      - "discovery.type=single-node"
 
  kibana:
    image: docker.elastic.co/kibana/kibana:7.14.2
    container_name: kibana
    depends_on:
      - elasticsearch
    ports:
      - 5601:5601
    environment:
      # IP地址為運行電腦的IP地址,Mac上通過 ifconfig en0 命令獲取
      - "elasticsearch.hosts=//192.168.1.5:9200" 

  skywalking-oap:
    image: apache/skywalking-oap-server:9.1.0
    container_name: skywalking-oap
    depends_on:
      - elasticsearch
    ports:
      - "11800:11800"
      - "12800:12800"
    healthcheck:
      test: [ "CMD-SHELL", "/skywalking/bin/swctl ch" ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    environment:
      TZ: Asia/Shanghai
      SW_STORAGE: elasticsearch
      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
      SW_HEALTH_CHECKER: default
      SW_TELEMETRY: prometheus

  skywalking-ui:
    image: apache/skywalking-ui:9.1.0
    container_name: skywalking-ui
    depends_on:
      - skywalking-oap
    links:
      - skywalking-oap
    ports:
     # UI界面程序佔用的端口
      - "8080:8080"
    environment:
      TZ: Asia/Shanghai
      # IP地址為運行電腦的IP地址,Mac上通過 ifconfig en0 命令獲取
      SW_OAP_ADDRESS: //192.168.1.8:12800

2.1 Docker鏡像加速

按上述配好docker-compose.yml文件後,命令行到所在目錄下執行docker-compose up可以拉起鏡像,第一次運行時會下載鏡像,docker默認的鏡像倉庫在國外,所以下載速度和蝸牛一樣慢。為了加速下載,需要配置國內的docker鏡像

獲取國內docker鏡像庫地址的方法:

  1. 阿里雲官方鏡像加速,獲取加速器地址文檔:阿里雲官方鏡像加速
  2. 網上搜索docker鏡像加速,下面是測過有效的公共鏡像庫

配置方法:

Docker桌面版Preference -> Docker Engine 在Json配置里加上,加好之後重啟Docker,然後再重新拉鏡像,速度立馬快得飛起🚀🚀🚀

  # 按需加上多個鏡像庫地址
  "registry-mirrors": [
		"//hub-mirror.c.163.com",
    "//mirror.baidubce.com"
  ]

2.2 Skywalking UI界面

docker啟動後,Skywalking第一次運行會自行在ES里創建索引,運行日誌沒有報錯,說明啟動成功了,瀏覽器打開//127.0.0.1:8080/可以看到Skywalking 的界面

2.3 Skywalking agent使用

數據的採集通過agent,Java應用啟動時通過-javaagent參數配置Skywalking agent。在IDEA中運行時,在啟動參數vm 中配置即可。

Skywalking Agent下載

官網上下載Java agent壓縮包Skywalking Agent下載,當前最新的版本是v8.12.0,下載到自己電腦上找個位置解壓。我的是放在/Users/longbig/opt/目錄下

shell腳本方式

# 配置agent地址,agent服務名,skywalking-oap collector地址(注意IP地址,因為我是docker運行,需要使用本機的局域網IP)
export JAVA_AGENT=-javaagent:/Users/yuyunlong/opt/skywalking-agent/skywalking-agent.jar=agent.service_name=multi_function,collector.backend_service=192.168.1.8:11800

# jar啟動
java -jar $JAVA_AGENT application.jar

IDEA運行方式

在你需要運行的springboot應用的VM options里加上上面的參數,啟動即可

啟動完之後隨便調用幾個接口試試,然後再在Skywalking的界面查看效果

2.3 追蹤數據

下面是我的服務的拓撲圖,服務之間的依賴關係可以看的非常清楚,如果旁友的應用比較多的話,能鋪滿整個屏幕的

到此Skywalking的搭建就完成了

3. Skywalking集成Logback實現Trace日誌打印

在之前的文章里,我們用了個簡陋的方法實現了traceId的傳遞全鏈路追蹤體驗—TraceId的生成,現在我們用上Skywalking框架來打印traceId

加上Maven依賴

        <!-- SkyWalking 對 Logback 的集成 -->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-logback-1.x</artifactId>
            <version>8.10.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-trace</artifactId>
            <version>8.10.0</version>
        </dependency>

logback-spring.xml文件修改內容:

主要修改2個地方

  • CONSOLE_LOG_PATTERN 里加上%tid,配置traceId佔位符
  • layout通過TraceIdPatternLogbackLayout 實現對%tid替換為Skywalking TraceId
    <!-- 彩色日誌 -->
    <!-- 彩色日誌依賴的渲染類 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日誌格式 -->
    <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} [%tid] %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

<!--輸出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日誌appender是為開發使用,只配置最底級別,控制台輸出的日誌級別是大於或等於此級別的日誌信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            </layout>
            <!-- 設置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

簡單測試看看

隨便寫了個探活接口,看看接口耗時和日誌打印效果

服務日誌打印:

界面traceId搜索

小結

本篇文章講了為什麼用分佈式鏈路追蹤以及Skywalking框架的使用,是對上一篇最簡陋traceId使用的進階版。學東西就是要日拱一卒,量變引起質變。我是卷福同學,一個在福報廠修福報中的小社畜哦~