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

本文涉及源碼都在 這里。

Apache Skywalking(Incubator)簡介

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

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

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

下載并安裝

下載

官網(wǎng) 下載合適的壓縮包,如果下載失?。ú恢罏樯段蚁螺d下來的是個空包),可以直接在這個 鏡像網(wǎng)站 下載。.zip 格式是 Windows 版本,.tar.gzLinux 版本, Mac 也用 .tar.gz 。

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

解壓

解壓壓縮包:

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

大致目錄樹結(jié)構(gòu)如下:


解壓后的目錄結(jié)構(gòu)

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

  • webapp: UI 前端(web 監(jiān)控頁面)的 jar 包和配置文件;
  • oap-libs: 后臺應用的 jar 包,以及它的依賴 jar 包,里邊有一個 server-starter-*.jar 就是啟動程序;
  • config: 啟動后臺應用程序的配置文件,是使用的各種配置
  • bin: 各種啟動腳本,一般使用腳本 startup.* 來啟動 web 頁面 和對應的 后臺應用;
    • oapService.*: 默認使用的后臺程序的啟動腳本;(使用的是默認模式啟動,還支持其他模式,各模式區(qū)別見 啟動模式
    • oapServiceInit.*: 使用 init 模式啟動;在此模式下,OAP服務器啟動以執(zhí)行初始化工作,然后退出
    • 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 的后端服務默認使用的數(shù)據(jù)庫是 h2,而我們需要使用的是 Mysql,所以得修改部分配置。該配置文件是目錄 config 下的 application.yml 文件,將 h2 數(shù)據(jù)庫相關(guān)配置注釋掉,然后 Mysql 部分去掉注釋,并將數(shù)據(jù)庫名、賬號密碼修改一下。修改完大致如下:

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}

注:如果沒有創(chuàng)建 skywalking 數(shù)據(jù)庫,還需要手動創(chuàng)建。

因為 oap-libs 目錄下缺少 mysql 的驅(qū)動程序,所以還需要下載 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/ 即可看到如下頁面:

監(jiān)控頁面

至此,Skywalking 的監(jiān)控跟蹤服務就準備完畢。

跟蹤分布式服務

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

目錄結(jié)構(gòu)

  • sca-skywalking-discovery:服務發(fā)現(xiàn)
  • sca-skywalking-gateway:網(wǎng)關(guān)
  • sca-skywalking-licence:licence 服務。里邊部分接口回調(diào)用 organization 服務的接口。
  • sca-skywalking-organization:organization 服務。

啟動服務

安裝Java agent 中,提到了在啟動應用之前,需要配置JVM參數(shù),添加 -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: 數(shù)據(jù)庫。因為服務 licence-service, organization 使用了 H2 數(shù)據(jù)庫
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 其實是占位符,優(yōu)先使用 SW_AGENT_NAME 的值,那這個到底是什么呢?其實是環(huán)境變量,如果啟動時環(huán)境變量 SW_AGENT_NAME 有值的話,那么使用它,否則使用默認值 Your_ApplicationName。

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

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


add env variables

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

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


topology

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

請求追蹤

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

trace with failed request

正常的請求長這樣:
trace

可以看到,一個請求的所有調(diào)用鏈都被記錄下來,包括 Spring MVC 的內(nèi)部轉(zhuǎn)發(fā)、跨服務的 http 調(diào)用以及數(shù)據(jù)庫查詢,都完整的記錄下來,而且也記錄了整個請求以及各個子步驟的耗時。

但是,有2個問題,第一,為啥沒有記錄網(wǎng)關(guān)層的調(diào)用鏈?第二,我剛剛其實只請求了幾次,為什么會有151頁數(shù)據(jù)?帶著這2個問題,我們繼續(xù)挖掘 Skywalking 的新特性。

使用 optional-plugins

兼容 SpringCloud Gateway

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

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

image.png

但是又有一個問題,為什么 SpringCloud Gateway 這么特殊呢,為啥沒一個類似 apm-spring-cloud-zuul-plugin-6.6.0.jar 的插件呢?這2個網(wǎng)關(guān)有啥本質(zhì)上的區(qū)別嗎?肯定有的啦,一個是同步的,另一個是異步(底層用了 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 相關(guān),看到這里,如果你比較熟悉 eureka 的底層邏輯,那么基本就能猜出來啥原因了:EurekaClient 每隔一段時間都會向 EurekaServer 請求續(xù)約,也可以理解為心跳,還有定時從 EurekaServer 拉取最新的可用的服務清單。

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

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

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

# 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/**}

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

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

ignore path

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

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

相關(guān)鏈接

官網(wǎng):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

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容