3 Skywalking應用
相關術語:
skywalking-collector:鏈路資料歸集器,資料可以落地ElasticSearch/H2
skywalking-ui:web可視化平臺,用來展示落地的資料
skywalking-agent:探針,用來收集和發送資料到歸集器
3.1 agent下載
Skywalking-agent,它簡稱探針,用來收集和發送資料到歸集器,我們先來學習下探針使用,探針對應的jar包在Skywalking原始碼中,我們需要先下載原始碼,
Skywalking原始碼下載地址: https://archive.apache.org/dist/skywalking/ ,我們當前使用的版本是8.3.0,選擇下載對應版本,

agent目錄結構如下:
agent
├── activations
│ ├── apm-toolkit-kafka-activation-8.3.0.jar
│ ├── ...
│ └── apm-toolkit-trace-activation-8.3.0.jar
├── config # Agent 組態檔
│ └── agent.config
├── logs # 日志檔案
├── optional-plugins # 可選插件
│ ├── apm-customize-enhance-plugin-8.3.0.jar
│ ├── apm-gson-2.x-plugin-8.3.0.jar
│ └── ... ...
├── bootstrap-plugins # jdk插件
│ ├── apm-jdk-http-plugin-8.3.0.jar
│ └── apm-jdk-threading-plugin-8.3.0.jar
├── plugins # 當前生效插件
│ ├── apm-activemq-5.x-plugin-8.3.0.jar
│ ├── apm-armeria-0.84.x-plugin-8.3.0.jar
│ ├── apm-armeria-0.85.x-plugin-8.3.0.jar
│ └── ... ...
├── optional-reporter-plugins
│ └── kafka-reporter-plugin-8.3.0.jar
└── skywalking-agent.jar【應用的jar包】
目錄結構說明:
activations 當前skywalking正在使用的功能組件,
agent.config 檔案是 SkyWalking Agent 的唯一組態檔,
plugins 目錄存盤了當前 Agent 生效的插件,
optional-plugins 目錄存盤了一些可選的插件(這些插件可能會影響整個系統的性能或是有著作權問題),如果需要使用這些插件,需將相應 jar 包移動到 plugins 目錄下,
skywalking-agent.jar 是 Agent 的核心 jar 包,由它負責讀取 agent.config 組態檔,加載上述插件 jar 包,運行時收集到 的 Trace 和 Metrics 資料也是由它發送到 OAP 集群的,
我們在使用Skywalking的時候,整個程序中都會用到skywalking-agent.jar,而無論是RPC還是HTTP開發的專案,用法都一樣,因此我們講解當前主流的SpringBoot專案對agent的使用即可,
3.2 agent應用
專案使用agent,如果是開發環境,可以使用IDEA集成,如果是生產環境,需要將專案打包上傳到服務器,為了使用agent,我們同時需要將下載的apache-skywalking-apm-bin檔案包上傳到服務器上去,不過無論是開發環境還是生產環境使用agent,對專案都是無侵入式的,
3.2.1 應用名配置
我們需要用到agent,此時需要將agent/config/agent.config組態檔拷貝到每個需要集成Skywalking工程的resource目錄下,我們將agent.config拷貝到工程\hailtaxi-parent的每個子工程目錄下,并修改其中的 agent.service_name,修改如下:
hailtaxi-gateway: agent.service_name=${SW_AGENT_NAME:hailtaxi-gateway}
hailtaxi-driver: agent.service_name=${SW_AGENT_NAME:hailtaxi-driver}
hailtaxi-order: agent.service_name=${SW_AGENT_NAME:hailtaxi-order}
agent.config 是一個 KV 結構的組態檔,類似于 properties 檔案,value 部分使用 "${}" 包裹,其中使用冒號(":")分為兩部分,前半部分是可以覆寫該配置項的系統環境變數名稱,后半部分為默認值,例如這里的 agent.service_name 配置項,如果系統環境變數中指定了 SW_AGENT_NAME 值(注意,全是大寫),則優先使用環境變數中指定的值,如果環境變數未指定,則使用 hailtaxi-driver 這個默認值,
直接把配置修改好后放到專案的resource目錄下(或者其他路徑)是最不容易才出錯的一種方式,同時我們可以采用其他方式覆寫默認值:
1)JVM覆寫配置
例如這里的 agent.service_name 配置項,如果在 JVM 啟動之前,明確中指定了下面的 JVM 配置:
# "skywalking."是 Skywalking環境變數的默認前綴
-Dskywalking.agent.service_name = hailtaxi-driver
2)探針配置覆寫
將 Java Agent 配置為如下:
# 默認格式是 -javaagent:agent.jar=[option1]=[value1],[option2]=[value2]
-javaagent:/path/skywalking-agent.jar=agent.service_name=hailtaxi-driver
此時會使用該 Java Agent 配置值覆寫 agent.config 組態檔中 agent.service_name 默認值,
但是這些配置都有不同優先級,優先級如下:
探針配置 > JVM配置 > 系統環境變數配置 > agent.config檔案默認值
3.2.2 IDEA集成使用agent
1、修改agent中資料收集服務的地址:agent/config/agent.confg
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:192.168.200.129:11800}
當然也可以同構JVM引數配置
2、使用探針配置為3個專案分別配置agent:
1)hailtaxi-driver:
-javaagent:C:\developer\skywalking\apache-skywalking-apm-bin\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=hailtaxi-driver
將上面配置賦值到IDEA中:

2)hailtaxi-order
-javaagent:C:\developer\skywalking\apache-skywalking-apm-bin\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=hailtaxi-order
將上面配置賦值到IDEA中:

3)hailtaxi-gateway
-javaagent:C:\developer\skywalking\apache-skywalking-apm-bin\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=hailtaxi-gateway
將上面配置賦值到IDEA中:

此時啟動IDEA,并訪問:http://192.168.200.129:8080 效果如下:

如果你要追蹤Gateway的話,你會發現:無法通過gateway發現路由的服務鏈路?
原因: Spring Cloud Gateway 是基于 WebFlux 實作,必須搭配上apm-spring-cloud-gateway-2.1.x-plugin 和 apm-spring-webflux-x.x-plugin 兩個插件
方案:將agent/optional-plugins下的兩個插件 復制到 agent/plugins目錄下
3.3.3 生產環境使用agent
生產環境使用,因此我們需要將agent和每個專案的jar包上傳到服務器上,上傳apache-skywalking-apm-bin至/usr/local/server/skywalking,再將工程\hailtaxi-parent中的專案打包,并分別上傳到服務器上,如下三個工程:
hailtaxi-order-1.0-SNAPSHOT.jar
hailtaxi-gateway-1.0-SNAPSHOT.jar
hailtaxi-driver-1.0-SNAPSHOT.jar
1)啟動hailtaxi-gateway
java -javaagent:/usr/local/server/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=hailtaxi-gateway -jar hailtaxi-gateway-1.0-SNAPSHOT.jar &
2)啟動hailtaxi-driver
java -javaagent:/usr/local/server/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=hailtaxi-driver -jar hailtaxi-driver-1.0-SNAPSHOT.jar &
3)啟動hailtaxi-order
java -javaagent:/usr/local/server/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=hailtaxi-order -jar hailtaxi-order-1.0-SNAPSHOT.jar &
3.3 Rocketbot
前面我們已經完成了SkyWalking環境搭建和專案應用agent使用,我們來看如何使用 SkyWalking 提供的 UI 界面—— Skywalking Rocketbot,
OAP服務和Rocket(其實就是個web專案)均已啟動

3.3.1 Rocketbot-儀表盤
具體細則可參考資料:Skywalking儀表盤使用

Rocketbot從多個方面展示了服務資訊,我們分別從多個方面進行講解,
上圖中的【儀表盤】、【拓撲圖】、【追蹤】、【性能剖析】、【日志】、【警告】屬于功能選單,
儀表盤屬于資料統計功能,分別從服務熱度、回應水平、服務個數、節點資訊等展示統計資料,
- Global Heatmap 面板:熱力圖,從全域展示了某段時間請求的熱度,
- Global Percent Response 面板 :展示了全域請求回應時間的 P99、P95、P75 等分位數,
- Global Brief 面板:展示了 SkyWalking 能感知到的 Service、Endpoint 的個數,
- Global Top Troughput 面板:展示了吞吐量前幾名的服務,
- Global Top Slow Endpoint 面板:展示了耗時前幾名的 Endpoint,
- Service (Avg) ResponseTime 面板:展示了指定服務的(平均)耗時,
- Service (Avg) Throughput 面板:展示了指定服務的(平均)吞吐量,
- Service (Avg) SLA 面板:展示了指定服務的(平均)SLA(Service Level Agreement,服務等級協議),
- Service Percent Response 面板:展示了指定服務回應時間的分位數,
- Service Slow Endpoint 面板:展示了指定服務中耗時比較長的 Endpoint 資訊,
- Running ServiceInstance 面板:展示了指定服務下的實體資訊,
除了 SkyWalking Rocketbot 默認提供的這些面板,我們還可以點擊鎖型按鈕,自定義 Global 面板,在 ServiceInstance 面板中展示了很多 ServiceInstance 相關的監控資訊,例如,JVM 記憶體使用情況、GC 次數、GC 耗時、CPU 使用率、ServiceInstance SLA 等等資訊,
3.3.2 Rocketbot-拓撲圖

【拓撲圖】展示當前整個業務服務的拓撲圖,點擊拓撲圖中的任意節點,可以看到服務相應的狀態資訊,其中包括回應的平均耗時、SLA 等監控資訊,點擊拓撲圖中任意一條邊,還可以看到一條呼叫鏈路的監控資訊,其中會分別從客戶端(上游呼叫方)和服務端(下游接收方)來觀測這條呼叫鏈路的狀態,其中展示了該條鏈路的耗時、吞吐量、SLA 等資訊,
3.3.3 追蹤

【追蹤】主要用來查詢 Trace 資訊,如下圖所示,在①處可以選擇 Trace 的查詢條件,其中可以指定 Trace 涉及到的 Service、ServiceInstance、Endpoint 以及Trace 的狀態繼續模糊查詢,還可以指定 TraceId 和時間范圍進行精確查詢,在②處可以直接根據請求連接查找呼叫鏈路資訊,在③處展示了 Trace 的簡略資訊,在④處可以選擇不同的方式展示追蹤資訊,
在這里,我們不僅能看到呼叫鏈路資訊,還能看到MySQL操作監控,如下圖:

錯誤例外資訊也能追蹤,如下圖:

3.3.4 性能分析
在傳統的監控系統中,我們如果想要得知系統中的業務是否正常,會采用行程監控、日志收集分析等方式來對系統進行監控,當機器或者服務出現問題時,則會觸發告警及時通知負責人,通過這種方式,我們可以得知具體哪些服務出現了問題,但是這時我們并不能得知具體的錯誤原因出在了哪里,開發人員或者運維人員需要到日志系統里面查看錯誤日志,甚至需要到真實的業務服務器上查看執行情況來解決問題,
如此一來,僅僅是發現問題的階段,可能就會耗費相當長的時間;另外,發現問題但是并不能追溯到問題產生具體原因的情況,也常有發生,這樣反反復復極其耗費時間和精力,為此我們便有了基于分布式追蹤的APM系統,
通過將業務系統接入分布式追蹤中,我們就像是給程式增加了一個放大鏡功能,可以清晰看到真實業務請求的整體鏈路,包括請求時間、請求路徑,甚至是操作資料庫的陳述句都可以看得一清二楚,通過這種方式,我們結合告警便可以快速追蹤到真實用戶請求的完整鏈路資訊,并且這些資料資訊完全是持久化的,可以隨時進行查詢,復盤錯誤的原因,
然而隨著我們對服務監控理解的加深,我們發現事情并沒有那么簡單,在分布式鏈路追蹤中我們有這樣的兩個流派:代碼埋點和位元組碼增強,無論使用哪種方式,底層邏輯一定都逃不過面向切面這個基礎邏輯,因為只有這樣才可以做到大面積的使用,這也就決定了它只能做到框架級別和RPC粒度的監控,這時我們可能依舊會遇到程式執行緩慢或者回應時間不穩定等情況,但無法具體查詢到原因,這時候,大家很自然的會考慮到增加埋點粒度,比如對所有的Spring Bean方法、甚至主要的業務層方法都加上埋點,但是這種思路會遇到不小的挑戰:
第一,增加埋點時系統開銷大,埋點覆寫不夠全面,通過這種方式我們確實可以做到具體業務場景具體分析,但隨著業務不斷迭代上線,弊端也很明顯:大量的埋點無疑會加大系統資源的開銷,造成CPU、記憶體使用率增加,更有可能拖慢整個鏈路的執行效率,雖然每個埋點消耗的性能很小,在微秒級別,但是因為數量的增加,甚至因為業務代碼重用造成重復埋點或者回圈使用,此時的性能開銷已經無法忽略,
第二,動態埋點作為一項埋點技術,和手動埋點的性能消耗上十分類似,只是減少的代碼修改量,但是因為通用技術的特別,上一個挑戰中提到的回圈埋點和重復使用的場景甚至更為嚴重,比如選擇所有方法或者特定包下的所有方法埋點,很可能造成系統性能徹底崩潰,
第三,即使我們通過合理設計和埋點,解決了上述問題,但是JDK函式是廣泛使用的,我們很難限制對JDK API的使用場景,對JDK過多方法、特別是非RPC方法的監控會造成系統的巨大延遲風險,而且有一些基礎型別和底層工具類,是很難通過位元組碼進行增強的,當我們的SDK使用不當或者出現bug時,我們無法具體得知真實的錯誤原因,
Skywalking中可以使用性能剖析分析特定端點的性能,我們需要先創建一個監控任務:

新建任務后,在右側可以查看任務性能分析報表,還可以點擊分析執行緒堆疊資訊,如下圖:

3.3.5 告警
SkyWalking 告警功能是在6.x版本新增的,其核心由一組規則驅動,這些規則定義在config/alarm-settings.yml檔案中, 告警的定義分為兩部分:
- 告警規則:它們定義了應該如何觸發度量警報,應該考慮什么條件,
- Webhook(網路鉤子):定義當警告觸發時,哪些服務終端需要被告知
3.3.5.1 警告規則詳解
Skywalking每隔一段時間根據收集到的鏈路追蹤的資料和配置的告警規則(如服務回應時間、服務回應時間百分比)等,判斷如果達到閾值則發送相應的告警資訊,發送告警資訊是通過呼叫webhook介面完成,具體的webhook介面可以使用者自行定義,從而開發者可以在指定的webhook介面中撰寫各種告警方式,比如郵件、短信等,告警的資訊也可以在RocketBot中查看到,
我們可以進入到Skywalking容器中,再進入到config檔案夾下就可以看到alarm-settings.yml,如下圖:

SkyWalking 的發行版都會默認提供config/alarm-settings.yml檔案,里面預先定義了一些常用的告警規則,如下:
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Sample alarm rules.
rules:
# Rule unique name, must be ended with `_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.
service_sla_rule:
# Metrics value need to be long, double or int
metrics-name: service_sla
op: "<"
threshold: 8000
# The length of time to evaluate the metrics
period: 10
# How many times after the metrics match the condition, will trigger alarm
count: 2
# How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
silence-period: 3
message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
service_resp_time_percentile_rule:
# Metrics value need to be long, double or int
metrics-name: service_percentile
op: ">"
threshold: 1000,1000,1000,1000,1000
period: 10
count: 3
silence-period: 5
message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
service_instance_resp_time_rule:
metrics-name: service_instance_resp_time
op: ">"
threshold: 1000
period: 10
count: 2
silence-period: 5
message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
# Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
# Because the number of endpoint is much more than service and instance.
#
# endpoint_avg_rule:
# metrics-name: endpoint_avg
# op: ">"
# threshold: 1000
# period: 10
# count: 2
# silence-period: 5
# message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
告警規則配置項的說明:
- Rule name:規則名稱,也是在告警資訊中顯示的唯一名稱,必須以
_rule結尾,前綴可自定義 - Metrics name:度量名稱,取值為
oal腳本中的度量名,目前只支持long、double和int型別, - Include names:該規則作用于哪些物體名稱,比如服務名,終端名(可選,默認為全部)
- Exclude names:該規則作不用于哪些物體名稱,比如服務名,終端名(可選,默認為空)
- Threshold:閾值
- OP: 運算子,目前支持
>、<、= - Period:多久告警規則需要被核實一下,這是一個時間視窗,與后端部署環境時間相匹配
- Count:在一個Period視窗中,如果values超過Threshold值(按op),達到Count值,需要發送警報
- Silence period:在時間N中觸發報警后,在TN -> TN + period這個階段不告警, 默認情況下,它和Period一樣,這意味著相同的告警(在同一個Metrics name擁有相同的Id)在同一個Period內只會觸發一次
- message:告警訊息
在組態檔中預先定義的告警規則總結如下:
- 在過去10分鐘內服務平均回應時間超過1秒達3次
- 在過去10分鐘內服務成功率低于80%達2次
- 在過去10分鐘內服務90%回應時間低于1秒達3次
- 在過去10分鐘內服務的回應時間超過1秒達2次
- 在過去10分鐘內端點的回應時間超過1秒達2次
這些警告資訊最侄訓在Skywalking-UI上展示,效果如下:

3.3.5.2 Webhook規則
Webhook配置其實是警告訊息接識訓呼處理,我們可以在程式中寫一個方法接收警告資訊,Skywalking會以application/json格式通過http請求發送,訊息格式宣告為:List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage,
欄位如下:
- scopeId, scope: 所有的scope物體在 org.apache.skywalking.oap.server.core.source.DefaultScopeDefine 里面宣告,
- name. 目標scope物體名稱,
- id0: scope物體ID,匹配名稱,
- id1: 不使用,
- ruleName: 配置在 alarm-settings.yml 里面的規則名稱.
- alarmMessage: 告警資訊.
- startTime:觸發告警的時間 示例:
[
{
"scopeId": 2,
"scope": "SERVICE_INSTANCE",
"name": "[email protected] of hailtaxi-driver",
"id0": "aGFpbHpdmVy.1_YzAwMAMTkyLjE2OC4xLjEwNA\u003d\u003d",
"id1": "",
"ruleName": "service_instance_resp_time_rule",
"alarmMessage": "Response time of service instance [email protected] of hailtaxi-driver is more than 1000ms in 2 minutes of last 10 minutes",
"startTime": 1611612258056
}
]
3.3.5.3 自定義Webhook訊息接收
我們按照如下步驟,可以在自己程式中接收警告資訊:
1)定義訊息接收物件
在hailtaxi-api中創建com.itheima.skywalking.model.AlarmMessage,代碼如下:
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class AlarmMessage {
private int scopeId;
private String name;
private String id0;
private String id1;
private String alarmMessage;
private long startTime;
String ruleName;
}
2)接收警告方法創建
在hailtaxi-driver中創建com.itheima.driver.controller.AlarmMessageController用于接收警告訊息,代碼如下:
一般情況下,這種接收告警的api會被放置在比較清閑的后臺服務中!!!
@RestController
@RequestMapping(value = "https://www.cnblogs.com/skywalking")
public class AlarmMessageController {
/***
* 接收警告資訊
* @param alarmMessageList
*/
@PostMapping("/webhook")
public void webhook(@RequestBody List<AlarmMessage> alarmMessageList) {
for (AlarmMessage alarmMessage : alarmMessageList) {
System.out.println("webhook:"+alarmMessage);
}
}
}
3)修改Webhook地址
修改alarm-settings.yml中的webhook地址:
webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
- http://192.168.200.10:8001/driver/skywalking/webhook
因為skywalking默認有一個告警規則:10分鐘內服務成功率低于80%超過2次
所以為了能演示出告警效果,我們在
hailtaxi-driver專案中的driver/info介面中添加一個一句話/**** * 司機資訊 */ //@GetMapping(value = "https://www.cnblogs.com/info/{id}") @RequestMapping(value = "https://www.cnblogs.com/info/{id}") public Driver info(@PathVariable(value = "https://www.cnblogs.com/jiagooushi/p/id")String id,HttpServletRequest request){ int i = 1/ 0; // 產生例外 Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()){ String name = headerNames.nextElement(); String value = https://www.cnblogs.com/jiagooushi/p/request.getHeader(name); System.out.println(name+":"+value); System.out.println("--------------------------"); } return driverService.findById(id); }測驗時將網關的條件斷言給注釋一下!!!
此時我們程式中就能接收警告資訊了,
本文由傳智教育博學谷 - 狂野架構師教研團隊發布
如果本文對您有幫助,歡迎關注和點贊;如果您有任何建議也可留言評論或私信,您的支持是我堅持創作的動力
轉載請注明出處!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/492162.html
標籤:Java
上一篇:Nodejs訊息佇列與宏任務佇列
