使用 SpringCloud(Gateway) + Skywalking + Mysql 做分布式跟蹤

本文涉及源碼都在 這里

Apache Skywalking(Incubator)簡介

Apache Skywalking(Incubator) 專門為微服務架構和云原生架構系統而設計并且支持分布式鏈路追蹤的APM系統。Apache Skywalking(Incubator)通過加載探針的方式收集應用調用鏈路信息,并對采集的調用鏈路信息進行分析,生成應用間關系和服務間關系以及服務指標。Apache Skywalking (Incubating)目前支持多種語言,其中包括Java.Net CoreNode.jsGo語言。

目前Skywalking已經支持從6個可視化維度剖析分布式系統的運行情況。總覽視圖是應用和組件的全局視圖,其中包括組件和應用數量,應用的告警波動,慢服務列表以及應用吞吐量;拓撲圖從應用依賴關系出發,展現整個應用的拓撲關系;應用視圖則是從單個應用的角度,展現應用的上下游關系,TopN的服務和服務器,JVM的相關信息以及對應的主機信息。服務視圖關注單個服務入口的運行情況以及此服務的上下游依賴關系,依賴度,幫助用戶針對單個服務的優化和監控;調用鏈展現了調用的單次請求經過的所有埋點以及每個埋點的執行時長;告警視圖根據配置閾值針對應用、服務器、服務進行實時告警。

英文版文檔:https://github.com/apache/skywalking/blob/master/docs/README.md
中文版文檔:https://skyapm.github.io/document-cn-translation-of-skywalking/

下載并安裝

下載

官網 下載合適的壓縮包,如果下載失敗(不知道為啥我下載下來的是個空包),可以直接在這個 鏡像網站 下載。.zip 格式是 Windows 版本,.tar.gzLinux 版本, Mac 也用 .tar.gz

本次使用的是目前最新穩定版 v6.6.0,而且到時使用 Mysql 做數據存儲,所以我下載的是這個 壓縮包

解壓

解壓壓縮包:

tar -zxvf apache-skywalking-apm-6.6.0.tar.gz

大致目錄樹結構如下:


解壓后的目錄結構

簡單說一下這幾個目錄的作用:

  • webapp: UI 前端(web 監控頁面)的 jar 包和配置文件;
  • oap-libs: 后臺應用的 jar 包,以及它的依賴 jar 包,里邊有一個 server-starter-*.jar 就是啟動程序;
  • config: 啟動后臺應用程序的配置文件,是使用的各種配置
  • bin: 各種啟動腳本,一般使用腳本 startup.* 來啟動 web 頁面 和對應的 后臺應用
    • oapService.*: 默認使用的后臺程序的啟動腳本;(使用的是默認模式啟動,還支持其他模式,各模式區別見 啟動模式
    • oapServiceInit.*: 使用 init 模式啟動;在此模式下,OAP服務器啟動以執行初始化工作,然后退出
    • oapServiceNoInit.*: 使用 no init模式啟動;在此模式下,OAP服務器不進行初始化。
    • webappService.*: UI 前端的啟動腳本;
    • startup.*: 組合腳本,同時啟動 oapService.*:webappService.* 腳本;
  • agent:
    • skywalking-agent.jar: 代理服務 jar
    • config: 代理服務啟動時使用的配置文件
    • plugins: 包含多個插件,代理服務啟動時會加載改目錄下的所有插件(實際是各種 jar 包)
    • optional-plugins: 可選插件,當需要支持某種功能時,比如 SpringCloud Gateway,則需要把對應的 jar 包拷貝到 plugins 目錄下;

啟動后端服務和前端UI

Skywalking 的后端服務默認使用的數據庫是 h2,而我們需要使用的是 Mysql,所以得修改部分配置。該配置文件是目錄 config 下的 application.yml 文件,將 h2 數據庫相關配置注釋掉,然后 Mysql 部分去掉注釋,并將數據庫名、賬號密碼修改一下。修改完大致如下:

storage:
... 省略部分
#  h2:
#    driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
#    url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db}
#    user: ${SW_STORAGE_H2_USER:sa}
#    metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}
  mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/skywalking"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root}
      dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
      dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
      dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
      dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
    metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}

注:如果沒有創建 skywalking 數據庫,還需要手動創建。

因為 oap-libs 目錄下缺少 mysql 的驅動程序,所以還需要下載 mysql-connector-java-*.jar 放到 oap-libs 目錄下,這里我使用的版本是 5.1.46。一般該 jar 包在本地的 maven 倉庫都有,直接拷貝過去即可,一般在目錄 ~/.m2/repository/mysql/mysql-connector-java/5.1.46 下。

$ cd apache-skywalking-apm-bin/bin
# 啟動
$ ./startup.sh
SkyWalking OAP started successfully!
SkyWalking Web Application started successfully!

# 查看啟動的服務
$ jps
17716 RemoteMavenServer
16005 Launcher
4295 OAPServerStartUp
18266 Jps
4301 skywalking-webapp.jar
...

如果看到 OAPServerStartUpskywalking-webapp.jar,那么代表2個服務都啟動成功。

這時訪問 http://localhost:8080/ 即可看到如下頁面:

監控頁面

至此,Skywalking 的監控跟蹤服務就準備完畢。

跟蹤分布式服務

這里 克隆到本地,本文用到的子項目為 spring-cloud-advance-skywalking,進入該目錄,可以看到包含如下服務:

目錄結構

  • sca-skywalking-discovery:服務發現
  • sca-skywalking-gateway:網關
  • sca-skywalking-licence:licence 服務。里邊部分接口回調用 organization 服務的接口。
  • sca-skywalking-organization:organization 服務。

啟動服務

安裝Java agent 中,提到了在啟動應用之前,需要配置JVM參數,添加 -javaagent:/path/to/skywalking-package/agent/skywalking-agent.jar。為了方便這里以在 IDEA 中啟動服務為例:

edit configurations

add jvm params

儀表盤(Dashboard)

啟動4個服務后,再次訪問 http://localhost:8080/ ,可以看到類似如下:

dashboard

拓撲圖(Topology)

再看下拓撲圖:


topology

Your_Application_Name: 服務名
localhost-1: 數據庫。因為服務 licence-service, organization 使用了 H2 數據庫
User: 暫時不知道是干啥的,以后知道了再補充(難道是skywalking的用戶服務?)

那么問題來了,為什么啟動了4個服務,這里只有一個 Your_Application_Name 服務?

其實在 安裝Java agent 中,有提到需要配置 config/agent.config 中的 agent.service_name。但我們這里需要啟動的服務有多個,直接配置在文件中肯定不合適,難道啟動一個服務改一次?

我們先來看下 config/agent.config 中的 agent.service_name 配置,如下:

# The service name in UI
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
... 省略前后其他配置

可以看到,屬性 agent.service_namevalue 其實是占位符,優先使用 SW_AGENT_NAME 的值,那這個到底是什么呢?其實是環境變量,如果啟動時環境變量 SW_AGENT_NAME 有值的話,那么使用它,否則使用默認值 Your_ApplicationName

所以這就不難解釋在拓撲圖中看到的只有一個 Your_ApplicationName,因為所有服務啟動時,都使用了同一份 agent.config 配置,skywalking 認為這4個服務都是服務名為 Your_ApplicationName 的4個實例。

所以我們可以在啟動時配置一下環境變量即可。如下:


add env variables

把4個服務都配置了 SW_AGENT_NAME 環境變量后,重新啟動。

再看下拓撲圖,會變成下面這樣:


topology

這樣就比較符合我們的預期了。因為 skywalking 有一定緩存機制,當服務不可用后,不會立即刪除(Your_ApplicationName),等過一段時間后會自動清清除。

請求追蹤

多次訪問 http://localhost:3100/licence/1,然后切到 追蹤 標簽頁,可以看到類似如下:

trace with failed request

正常的請求長這樣:
trace

可以看到,一個請求的所有調用鏈都被記錄下來,包括 Spring MVC 的內部轉發、跨服務的 http 調用以及數據庫查詢,都完整的記錄下來,而且也記錄了整個請求以及各個子步驟的耗時。

但是,有2個問題,第一,為啥沒有記錄網關層的調用鏈?第二,我剛剛其實只請求了幾次,為什么會有151頁數據?帶著這2個問題,我們繼續挖掘 Skywalking 的新特性。

使用 optional-plugins

兼容 SpringCloud Gateway

前面提到,agent 目錄下有 pluginsoptional-plugins 2個目錄,skywalking-agent.jar 在啟動時會加載 plugins 下的所有插件,但不會加載 optional-plugins 下的,其實看目錄名就知道了,可選插件 就是可有可沒有,需要等需要的時候再加到 plugins 下即可。

我們看到, optional-plugins 下就有跟 SpringCloud Gateway 相關的插件,那就它了,把它丟到 plugins 目錄下。

image.png

但是又有一個問題,為什么 SpringCloud Gateway 這么特殊呢,為啥沒一個類似 apm-spring-cloud-zuul-plugin-6.6.0.jar 的插件呢?這2個網關有啥本質上的區別嗎?肯定有的啦,一個是同步的,另一個是異步(底層用了 netty,還依賴 spring-webflux)。另外,我們還注意到另一個插件 apm-spring-webflux-5.x-plugin-6.6.0.jar,把它也丟到 plugins 目錄下。

最后,重啟4個服務,再訪問 http://localhost:3100/licence/1,可以看到如下:

trace with springcloud gateway

這樣,第一個問題就解決了。

自定義忽略追蹤部分請求

首先,我們不妨跳到50頁,如下:


image.png

可以看到所有都是跟 eureka 相關,看到這里,如果你比較熟悉 eureka 的底層邏輯,那么基本就能猜出來啥原因了:EurekaClient 每隔一段時間都會向 EurekaServer 請求續約,也可以理解為心跳,還有定時從 EurekaServer 拉取最新的可用的服務清單。

這種記錄這些請求對我們來說用處不大,而且還會造成大量垃圾數據,所以應該避免追蹤,但 Skywalking 并不能自己識別出來,拿只能我們教它怎么分辨了。

注意到,optional-plugins 中有這樣的插件 apm-trace-ignore-plugin-6.6.0.jar,把它丟到 plugins 目錄下先。

加上插件只是讓 Skywalking 擁有忽略某些請求的能力,但還需要我們指定哪些需要忽略。下載 配置文件,然后把它丟到 /agent/config/ 目錄下,增加過濾規則。里邊的內容如下:

# If the operation name of the first span is matching, this segment should be ignored
#  ant path match style
#  /path/?   Match any single character
#  /path/*   Match any number of characters
#  /path/**  Match any number of characters and support multilevel directories
#  Multiple path comma separation, like trace.ignore_path=/eureka/**,/consul/**
#trace.ignore_path=${SW_AGENT_TRACE_IGNORE_PATH:/eureka/**}

可以看到插件的開發者已經幫我們考慮到 eureka 這種情況了,直接去掉最后一行的注釋即可,當然,也可以跟服務名一樣使用環境變量配置。另外,eureka-server 因為不是我們的業務服務,所以可以考慮不對它進行代理,即去掉 JVM 參數配置。

最后,重啟4個服務,再訪問 http://localhost:3100/licence/1,可以看到如下:

ignore path

可以看到清爽很多,沒有太多冗余的請求。

相關配置可參考:支持忽略自定義的traceSupport custom trace ignore

相關鏈接

官網:https://skywalking.apache.org/
英文版文檔:https://github.com/apache/skywalking/blob/master/docs/README.md
中文版文檔:https://skyapm.github.io/document-cn-translation-of-skywalking/
配置覆蓋:https://skyapm.github.io/document-cn-translation-of-skywalking/zh/master/setup/service-agent/java-agent/Setting-override.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。