SkyWalking
簡介
分布式鏈路跟蹤是分布式系統的應用程序性能監視工具,專為微服務、雲原生架構和基於容器(Docker、K8s)架構而設計;
也就是說Skywalking是用於微服務的“跟蹤" ;
對於一個大型的幾十個、幾百個微服務構成的微服務架構系統,通常會遇到下面一些問題,比如:
如何串聯整個調用鏈路,快速定位問題?
如何理清各個微服務之間的依賴關系?
如何進行各個微服務接口的性能分折?
如何跟蹤整個業務流程的調用處理順序?
Skywalking提供分布式追蹤、服務網格遙測分析、度量聚合和可視化一體化解決方案;
Skywalking是國人采用Java開發的,現在已經是apache下的一個等級項目;
主要功能和特征
1、多種監控手段,可以通過語言探針和service mesh獲得監控的數據;
2、支持多種語言自動探針,包括 Java,.NET Core 和 Node.JS;
3、輕量高效,無需大數據平台和大量的服務器資源;
4、模塊化,UI、存儲、集群管理都有多種機制可選;
5、支持告警;
6、優秀的可視化解決方案;
官網:http://skywalking.apache.org/
下載:http://skywalking.apache.org/downloads/
Github:https://github.com/apache/skywalking
使用公司:(國內非常多)
整體架構
整個架構分成四部分:
1、上部分Agent :負責從應用中,收集鏈路信息,發送給 SkyWalking OAP 服務器;
2、下部分 SkyWalking OAP :負責接收Agent發送的Tracing數據信息,然后進行分析(Analysis Core),存儲到外部存儲器(Storage),最終提供查詢(Query)功能;
3、右部分Storage:Tracing數據存儲,目前支持ES、MySQL、Sharding Sphere、TiDB、H2多種存儲器,目前采用較多的是ES,主要考慮是SkyWalking開發團隊自己的生產環境采用ES為主;
4、左部分SkyWalking UI:負責提供控台,查看鏈路等等;
環境部署

1,下載 SkyWalking 軟件包;
2,搭建一個 SkyWalking OAP 和SkyWalking UI服務;
3,啟動一個Spring Boot應用,並配置SkyWalking Agent;
數據存儲暫時先使用它默認的H2數據庫存儲,后續我們再使用其他存儲;
1、下載 SkyWalking 軟件包
對於 SkyWalking 的軟件包,有兩種方式獲取:
手動編譯
官方包
一般情況下,我們建議使用官方包,手動編譯也可以;
從這里下載:http://skywalking.apache.org/downloads/
2、SkyWalking OAP 搭建
解壓:tar -zxvf apache-skywalking-apm-8.1.0.tar.gz
解壓后即完成了安裝,不需要做其他操作;
切換:cd apache-skywalking-apm-bin
目錄說明:
agent #SkyWalking Agent
bin #執行腳本
config #SkyWalking OAP Server 配置文件
LICENSE
licenses
NOTICE
oap-libs #SkyWalking OAP Server
README.txt
tools
webapp #SkyWalking UI
3、啟動 SkyWalking OAP 服務
切換到bin目錄:./startup.sh
啟動后會啟動兩個服務,一個是skywalking-oap-server,一個是skywalking-web-ui;
查看安裝目錄下的 ./logs 下的日志文件,檢查兩個服務的日志文件是否啟動成功;
skywalking-oap-server服務啟動后會占用:11800 和 12800 兩個端口;
skywalking-web-ui服務會占用 8080 端口;
如果想要修改SkyWalking UI服務的參數,可以編輯webapp/webapp.yml 配置文件,比如:
server.port:SkyWalking UI服務端口,默認是8080;
collector.ribbon.listOfServers:SkyWalking OAP服務地址數組,SkyWalking UI界面的數據是通過請求SkyWalking OAP服務來獲得;
訪問SkyWalking UI界面:http://192.168.172.128:8080/
頁面的右下角可以中英文切換,可以切換選擇要展示的時間區間的跟蹤數據;
SkyWalking Agent跟蹤微服務
案例一:
准備一個springboot程序,打成可執行jar包,寫一個shell腳本,在啟動項目的Shell腳本上,通過 -javaagent 參數進行配置SkyWalking Agent來跟蹤微服務;
#!/bin/sh
\# SkyWalking Agent配置
export SW_AGENT_NAME=11-springboot #Agent名字,一般使用`spring.application.name`
export SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 #配置 Collector 地址。
export SW_AGENT_SPAN_LIMIT=2000 #配置鏈路的最大Span數量,默認為 300。
export JAVA_AGENT=-javaagent:/usr/local/apache-skywalking-apm-bin/agent/skywalking-agent.jar
java ***\*$JAVA_AGENT\**** -jar 11-springboot-1.0.0.jar #jar啟動
在啟動程序前加一個-javaagent 參數即可完成對程序的跟蹤;
案例二:
在tomcat中部署war包配置SkyWalking Agent來跟蹤微服務;
修改/usr/local/apache-tomcat-9.0.31/bin/catalina.sh 文件,在頂部第一行加上:
CATALINA_OPTS="$CATALINA_OPTS -javaagent:/usr/local/apache-skywalking-apm-bin/agent/skywalking-agent.jar";
export CATALINA_OPTS;
如果tomcat端口與skywalking ui端口沖突的話,修改一下tomcat端口;
測試,訪問一下項目,然后進入 SkyWalking UI 界面查看跟蹤情況,由於上傳數據是異步的,訪問完項目后,可能需要等幾秒才能看到跟蹤數據;
SkyWalking三個概念
*服務(Service)* *:*表示對請求提供相同行為的一系列或一組工作負載,在使用Agent時,可以定義服務的名字,我們可以看到 Spring Boot 應用服務為 "11-springboot",就是我們在環境變量 SW_AGENT_NAME 中所定義的;
*服務實例(Service Instance) :*上述的一組工作負載中的每一個工作負載稱為一個實例, 一個服務實例實際就是操作系統上的一個真實進程;
這里我們可以看到 Spring Boot 應用的服務為 {agent_name}-pid:{pid}@{hostname},由 Agent 自動生成;
*端點(Endpoint) :*對於特定服務所接收的請求路徑, 如HTTP的URI路徑和gRPC服務的類名 + 方法簽名;
我們可以看到 Spring Boot 應用的一個端點,為API接口 /index;
IDEA中使用SkyWalking
在運行的程序配置jvm參數和環境變量參數,如下圖所示:
-javaagent:E:\software\JAVA\springcloud-alibaba\package\skywalking\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800;SW_AGENT_NAME=sharding
SkyWalking告警
告警設置:./config/alarm-setting.yml
skywalking告警的核心由一組規則驅動,這些規則定義在config/alarm-settings.yml文件中,告警規則的定義分為三部分;
1、告警規則:它們定義了應該如何觸發度量警報,應該考慮什么條件;
2、網絡鈎子(Webhook}:當警告觸發時,哪些服務終端需要被通知;
3、gRPC鈎子:遠程gRPC方法的主機和端口,告警觸發后調用;
為了方便,skywalking發行版中提供了默認的alarm-setting.yml文件,包括一些規則,每個規則有英文注釋,可以根據注釋得知每個規則的作用;
比如service_resp_time_rule規則:
service_resp_time_rule:
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
該規則表示服務{name}的響應時間在最近10分鍾的3分鍾內超過1000ms;
只有我們的服務請求符合alarm-setting.yml文件中的某一條規則就會觸發告警;
*Webhook回調通知*
SkyWalking告警Webhook回調要求接收方是一個Web容器(比如tomcat服務),告警的消息會通過HTTP請求進行發送, 請求方法為POST, Content-Type為application/json, JSON格式基於
List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>的集合對象數據, 集合中的每個AlarmMessage包含以下信息:
1、scopeId. 所有可用的Scope請查閱:
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
2、name. 目標 Scope 的實體名稱;
3、id0. Scope 實體的 ID;
4、id1. 未使用;
5、ruleName. 您在 alarm-settings.yml 中配置的規則名;
6、alarmMessage. 報警消息內容;
7、startTime. 告警時間, 位於當前時間與 UTC 1970/1/1 之間;
AlarmMessage類的代碼:
SkyWalking數據mysql持久化
在./config/application.yml文件中將數據存儲那一項變更為mysql
在MySQL下,變更連接url,更改連接數據庫的用戶名和密碼。在oap-libs文件夾下導入mysql驅動。啟動skywalking即可。
SkyWalking數據Elasticsearch持久化
Skywalking跟蹤數據默認是存放在內嵌式數據庫H2中的,重啟skywalking,跟蹤數據就丟失了,我們可以把跟蹤數據持久化到mysql或者elasticsearch中,上一次課我們介紹了如何將跟蹤數據持久化到mysql,此次我們介紹一些如何將跟蹤數據持久化到elasticsearch中;
需要解壓另一個專門針對elasticsearch版本的Skywalking:
1、tar -zxvf apache-skywalking-apm-es7-8.1.0.tar.gz
2、cd apache-skywalking-apm-es7-8.1.0
3、修改application.yml配置文件:
storage:
selector: ${SW_STORAGE:elasticsearch7}
4、啟動elasticsearch7
./elasticsearch -d
后台運行 (es不能用root啟動)
注:Elasticsearch的jvm內存不能配置太小,至少512m,小了會出現錯誤:
配置文件:./config/jvm.options
status line [HTTP/1.1 429 Too Many Requests] <------錯誤信息
5、啟動elasticsearch-head插件:npm run start 便於查看elasticsearch數據;
6、啟動skywalking
./startup.sh
啟動時會向elasticsearch中創建大量的index索引用於持久化數據,每天會產生一個新的索引文件;
7、啟動應用程序,查看跟蹤數據是否已經持久化到elasticsearch的索引中;
8、然后重啟skywalking,驗證跟蹤數據會不會丟失;
Skywalking跨多個微服務跟蹤
Skywalking跨多個微服務跟蹤,只需要每個微服務啟動時添加javaagent參數即可;
-javaagent:D:/dev/apache-skywalking-apm-bin/agent/skywalking-agent.jar
SW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.172.128:11800;SW_AGENT_NAME=11-springboot-idea
自定義SkyWalking鏈路追蹤
如果我們希望對項目中的業務方法,實現鏈路追蹤,方便我們排查問題,可以使用如下的代碼;
1、添加依賴;
<!-- SkyWalking 工具類-->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.6.0</version>
</dependency>
2、在業務代碼中使用如下方法:
TraceContext.putCorrelation("myKey", "myValue");
Optional<String> op = TraceContext.getCorrelation("myKey");
log.info("myValue = {} ", op.get());
String traceId = TraceContext.traceId();
log.info("traceId = {} ", traceId);
這樣就可以拿到跟蹤的traceId,便於根據traceId去ui界面搜索整個跟蹤鏈路;
另外如果一個業務方法想在ui界面的跟蹤鏈路上顯示出來,只需要在業務方法上加上@Trace
注解即可;
SkyWalking集成日志框架
1、添加如下依賴;
<!-- apm-toolkit-logback-1.x -->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.6.0</version>
</dependency>
2、添加logback-spring.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 引入 Spring Boot 默認的 logback XML 配置文件 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 控制台 Appender -->
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %tid %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">
<!-- 日志的格式化 -->
<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>
</encoder>
</appender>
<!-- 從 Spring Boot 配置文件中,讀取 spring.application.name 應用名 -->
<springProperty name="applicationName" scope="context" source="spring.application.name" />
<property name="FILE_LOG_PATTERN" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } %tid --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 日志文件的路徑 -->
<property name="LOG_FILE" value="/logs/${applicationName}.log"/>
<!-- 日志文件 Appender -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<!--滾動策略,基於時間 + 大小的分包策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<!-- 日志的格式化 -->
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</layout>
</encoder>
</appender>
<!-- 設置 Appender -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
</configuration>
3、在代碼中記錄日志:
log.info("/goods --> getAllGoods --> ......" ); //自定義log輸出
4、訪問controller測試,查看日志輸出,就可以在日志中看到跟蹤的traceId;
SkyWalking-UI介紹
儀表盤:查看被監控服務的運行狀態;
拓撲圖:以拓撲圖的方式展現服務之間的關系,並以此為入口查看相關信息;
追蹤:以接口列表的方式展現,追蹤接口內部調用過程;
性能剖析:對端點進行采樣分析,並可查看堆棧信息;
告警:觸發告警的告警列表,包括服務失敗率,請求超時等;
自動刷新:刷新當前頁面數據內容;
控制欄
第一欄:不同內容主題的監控面板,應用性能管理/數據庫/容器等;
第二欄:操作,包括 編輯/導出當前數據/倒入展示數據/不同服務端點篩選展示;
第三欄:不同緯度展示,全局/服務/實例/端點;
展示欄
Global全局維度
第一欄:Global、Service、Instance、Endpoint不同展示面板;
Services load:服務每分鍾請求數;
Slow Services:慢響應服務,單位ms;
Un-Health services(Apdex): Apdex性能指標,1為滿分;
Slow Endpoint:慢響應端點,單位ms;
Global Response Latency:百分比響應延時,不同百分比的延時時間,單位ms;
Global Heatmap:服務響應時間熱力分布圖,根據時間段內不同響應時間的數量顯示顏色深度;
底部欄:展示數據的時間區間,點擊可以調整;
Service服務維度
Service Apdex(數字):當前服務的評分;
Service Apdex(折線圖):不同時間的Apdex評分;
Service Avg Response Times:平均響應延時,單位ms;
Global Response Time Percentile:百分比響應延時;
Successful Rate(數字):請求成功率;
Successful Rate(折線圖):不同時間的請求成功率;
Servce Load(數字):每分鍾請求數;
Servce Load(折線圖):不同時間的每分鍾請求數;
Servce Instances Load:每個服務實例的每分鍾請求數;
Show Service Instance:每個服務實例的最大延時;
Service Instance Successful Rate:每個服務實例的請求成功率;
Instance實例維度
Service Instance Load:當前實例的每分鍾請求數;
Service Instance Successful Rate:當前實例的請求成功率;
Service Instance Latency:當前實例的響應延時;
JVM CPU:jvm占用CPU的百分比;
JVM Memory:JVM內存占用大小,單位m;
JVM GC Time:JVM垃圾回收時間,包含YGC和OGC;
JVM GC Count:JVM垃圾回收次數,包含YGC和OGC;
JVM Thread Count:JVM線程數;
還有幾個是.NET的,類似於JVM虛擬機,暫時不做說明;
Endpoint端點(API)維度
Endpoint Load in Current Service:每個端點的每分鍾請求數;
Slow Endpoints in Current Service:每個端點的最慢請求時間,單位ms;
Successful Rate in Current Service:每個端點的請求成功率;
Endpoint Load:當前端點每個時間段的請求數據;
Endpoint Avg Response Time:當前端點每個時間段的請求行響應時間;
Endpoint Response Time Percentile:當前端點每個時間段的響應時間占比;
Endpoint Successful Rate:當前端點每個時間段的請求成功率;
拓撲圖
1:選擇不同的服務關聯拓撲;
2:查看單個服務相關內容;
3:服務間連接情況;
4:分組展示服務拓撲;
追蹤
左側:api接口列表,紅色-異常請求,藍色-正常請求;
右側:api追蹤列表,api請求連接各端點的先后順序和時間;
性能剖析
服務:需要分析的服務;
端點:鏈路監控中端點的名稱,可以在鏈路追蹤中查看端點名稱;
監控時間:采集數據的開始時間;
監控持續時間:監控采集多長時間;
起始監控時間:多少秒后進行采集;
監控間隔:多少秒采集一次;
最大采集數:最大采集多少樣本;
告警
不同維度告警列表,可分為服務、端點和實例;
SkyWalking集群-Nacos
生產中不搭集群也是可以的,因為這個只是調用鏈路跟蹤,skywalking oap跟蹤服務如果宕機了,完全不會影響正常業務;
Skywalking集群是將skywalking oap作為一個服務注冊到nacos上,只要skywalking oap服務沒有全部宕機,保證有一個skywalking oap在運行,就能進行跟蹤;
搭建一個skywalking oap集群需要:
(1)至少一個Nacos(也可以nacos集群)
(2)至少一個ElasticSearch(也可以es集群)
(3)至少2個skywalking oap服務;
(4)至少1個UI(UI也可以集群多個,用Nginx代理統一入口)
具體步驟:
1、解壓兩份apache-skywalking-apm-es7-8.1.0.tar.gz
2、修改配置application.yml文件
/config/application.yml
cluster:
selector: ${SW_CLUSTER:nacos}
nacos:
serviceName: ${SW_SERVICE_NAME:"SkyWalking_OAP_Cluster"}
hostPort: ${SW_CLUSTER_NACOS_HOST_PORT:localhost:8848}
注意:nacos配置中的命名空間是否正確
第一台
restHost: ${SW_CORE_REST_HOST:0.0.0.0}
restPort: ${SW_CORE_REST_PORT:12801}
gRPCPort: ${SW_CORE_GRPC_PORT:11801}
gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
第二台
restHost: ${SW_CORE_REST_HOST:0.0.0.0}
restPort: ${SW_CORE_REST_PORT:12802}
gRPCPort: ${SW_CORE_GRPC_PORT:11802}
gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
使用elasticsearch作為storage
storage:
selector: ${SW_STORAGE:elasticsearch7}
storage:
elasticsearch7:
nameSpace: ${SW_NAMESPACE:""}
clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
3、配置ui服務webapp.yml文件的listOfServers,寫兩個地址
listOfServers: 127.0.0.1:12801,127.0.0.1:12802
4、啟動測試
啟動一個skywalking-webapp.jar使用腳本webappService.sh;
啟動兩個OAPServerStartUp使用腳本oapService.sh;
5、啟動應用程序進行測試,如果是jar包啟動:
java -javaagent:xxxxx/agent/skywalking-agent.jar
-Dskywalking.agent.service_name=gateway
-Dskywalking.collector.backend_service=192.168.172.128:11801,192.168.172.128:11802
-jar 11-springboot-idea-1.0.0.jar
如果是idea啟動應用程序:(注意配置兩個連接地址)
SW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.172.128:11801,192.168.172.128:11802;SW_AGENT_NAME=11-springboot-idea