一站式雲原生可觀測性利器:SkyWalking讓應用監控如虎添翼|DevOps必備

目錄
  • OpenTracing規範
    • 為什麼需要OpenTracing
    • 什麼是一個Trace
    • 一個典型的Trace案例
  • Skywalking
    • 功能介紹
    • 整體架構
    • Tracing、Logging和Metrics
  • .NET6 對接 Skywalking
    • 新增依賴
    • 編輯Skywalking配置檔案skyapm.json
    • launchSettings.json檔案配置SK
    • startup.cs檔案中新增
    • 安裝CLI(SkyAPM.DotNet.CLI)
    • 自動生成skyapm.json檔案
    • 手動編寫skyapm.json
    • 自動生成Skyapm.json
    • 獲取traceId
    • 自定義呼叫鏈路的資訊
    • 部署Skywalking環境
    • 對接.NET6 程式
  • 接入微服務閘道器+後臺微服務
    • 新增依賴
    • 複製配置檔案並簡單修改
    • launchsettings.json新增環境變數
    • 啟動訂單微服務
    • 新增依賴
    • 複製配置檔案並簡單修改
    • launchsettings.json新增環境變數
    • 修改閘道器配置檔案,新增OrderServiceInstance微服務的路由
    • 啟動閘道器
    • 閘道器接入
    • 訂單微服務接入
    • 使用者微服務接入
  • 配置Skywalking告警
    • 配置告警規則
    • 查閱配置規則檔案及配置規則解讀
    • 修改告警規則
    • 告警API編寫

OpenTracing規範

OpenTracing是一種分散式系統鏈路跟蹤的設計原則、規範、標準。類似JDBC的規範,主要為了提供一套標準的JDBC API。OpenTracing也是一樣,是為了統一提供一套鏈路追蹤的標準API,所制定的一種規範。OpenTracing透過提供平臺無關、廠商無關的API,使得開發人員能夠方便的新增(或更換)追蹤系統的實現。

為什麼需要OpenTracing

OpenTracing透過提供平臺無關、廠商無關的API,使得開發人員能夠方便的新增(或更換)追蹤系統的實現。 OpenTracing提供了用於運營支撐系統的和針對特定平臺的輔助程式庫。

什麼是一個Trace

在廣義上,一個trace代表了一個事務或者流程在(分散式)系統中的執行過程。在OpenTracing標準中,trace是多個span組成的一個有向無環圖(DAG),每一個span代表trace中被命名並計時的連續性的執行片段。
分散式追蹤中的每個元件都包含自己的一個或者多個span。例如,在一個常規的RPC呼叫過程中,OpenTracing推薦在RPC的客戶端和服務端,至少各有一個span,用於記錄RPC呼叫的客戶端和服務端資訊。
一個父級的span會顯示的並行或者序列啟動多個子span。在OpenTracing標準中,甚至允許一個子span有個多父span(例如:並行寫入的快取,可能透過一次重新整理操作寫入動作)。

一個典型的Trace案例

在一個分散式系統中,追蹤一個事務或者呼叫流一般如上圖所示。雖然這種圖對於看清各元件的組合關係是很有用的,但是,它不能很好顯示元件的呼叫時間,是序列呼叫還是並行呼叫,如果展現更復雜的呼叫關係,會更加複雜,甚至無法畫出這樣的圖。另外,這種圖也無法顯示呼叫間的時間間隔以及是否透過定時呼叫來啟動呼叫。一種更有效的展現一個典型的trace過程,如下圖所示:
這種展現方式增加顯示了執行時間的上下文,相關服務間的層次關係,程序或者任務的序列或並行呼叫關係。這樣的檢視有助於發現系統呼叫的關鍵路徑。透過關注關鍵路徑的執行過程,專案團隊可能專注於最佳化路徑中的關鍵位置,最大幅度的提升系統性能。例如:可以透過追蹤一個資源定位的呼叫情況,明確底層的呼叫情況,發現哪些操作有阻塞的情況。

Skywalking

Skywalking是一款APM(Application Performance Management & Monitoring)系統。Skywalking是分散式系統應用程式效能監視工具,專為微服務、雲原生架構和基於容器(Docker、K8s、Mesos)架構而設計。提供分散式追蹤、服務網格遙測分析、度量聚合和視覺化一體化解決方案。

功能介紹

  • 多種監控手段。可以透過語言探針和 service mesh 獲得監控是資料。
  • 多個語言自動探針。包括 Java,.NET Core 和 Node.JS。
  • 輕量高效。無需大資料平臺,和大量的伺服器資源。
  • 模組化。UI、儲存、叢集管理都有多種機制可選。
  • 支援告警。
  • 優秀的視覺化解決方案。

整體架構

整個架構,分成上、下、左、右四部分:
  • 探針基於不同的來源可能是不一樣的, 但作用都是收集資料, 將資料格式化為 SkyWalking 適用的格式.
  • 平臺後端是一個支援叢集模式執行的後臺, 用於資料聚合, 資料分析以及驅動資料流從探針到使用者介面的流程. 平臺後端還提供了各種可插拔的能力, 如不同來源資料(如來自 Zipkin)格式化, 不同儲存系統以及叢集管理. 你甚至還可以使用觀測分析語言來進行自定義聚合分析.
  • 儲存是開放式的. 你可以選擇一個既有的儲存系統, 如 ElasticSearch, H2 或 MySQL 叢集(Sharding-Sphere 管理), 也可以選擇自己實現一個儲存系統. 當然, 我們非常歡迎你貢獻新的儲存系統實現.
  • 使用者介面對於 SkyWalking 的終端使用者來說非常炫酷且強大. 同樣它也是可定製以匹配你已存在的後端的

Tracing、Logging和Metrics

在微服務領域,很早以來就形成了Tracing、Logging和Metrics相輔相成,合力支撐多維度、多形態的監控體系,三類監控各有側重:
Tracing:它在單次請求的範圍內,處理資訊。 任何的資料、元資料資訊都被繫結到系統中的單個事務上。例如:一次呼叫遠端服務的RPC執行過程;一次實際的SQL查詢語句;一次HTTP請求的業務性ID;
Logging:日誌,不知道大家有沒有想過它的定義或者邊界。Logging即是記錄處理的離散事件,比如我們應用的除錯資訊或者錯誤資訊等傳送到ES;審計跟蹤時間資訊透過Kafka處理送到BigTable等資料倉儲等等,大多數情況下記錄的資料很分散,並且相互獨立,也許是錯誤資訊,也許僅僅只是記錄當前的事件狀態,或者是警告資訊等等。
Metrics:當我們想知道我們服務的請求QPS是多少,或者當天的使用者登入次數等等,這時我們可能需要將一部分事件進行聚合或計數,也就是我們說的Metrics。可聚合性即是Metrics的特徵,它們是一段時間內某個度量(計數器或者直方圖)的原子或者是元資料。例如接收的HTTP數量可以被建模為計數器,每次的HTTP請求即是我們的度量元資料,可以進行簡單的加法聚合,當持續了一段時間我們又可以建模為直方圖。

.NET6 對接 Skywalking

部署Skywalking環境

version: '3.3'

services:

elasticsearch:

image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0

container_name: elasticsearch

restart: always

ports:

- 9200:9200

environment:

- discovery.type=single-node

- bootstrap.memory_lock=true

- "ES_JAVA_OPTS=-Xms256m -Xmx256m"

ulimits:

memlock:

soft: -1

hard: -1

oap:

image: apache/skywalking-oap-server:6.6.0-es7

container_name: oap

depends_on:

- elasticsearch

links:

- elasticsearch

restart: always

ports:

- 11800:11800

- 12800:12800

environment:

SW_STORAGE: elasticsearch

SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200

ui:

image: apache/skywalking-ui:6.6.0

container_name: ui

depends_on:

- oap

links:

- oap

restart: always

ports:

- 8080:8080

environment:

SW_OAP_ADDRESS: http://oap:12800

安裝成功以後首頁地址:http://伺服器IP:8080

對接.NET6 程式

新增依賴

<ItemGroup>
<PackageReferenceInclude="SkyAPM.Agent.AspNetCore"Version="1.3.0" />
</ItemGroup>

編輯Skywalking配置檔案skyapm.json

手動編寫skyapm.json

{
"SkyWalking":{
"ServiceName":"MySkyWalkingDemoTest",
"Namespace":"",
"HeaderVersions":[
"sw8"
],
"Sampling":{
"SamplePer3Secs":-1,
"Percentage":-1.0
},
"Logging":{
"Level":"Information",
"FilePath":"logs\\skyapm-{Date}.log"
},
"Transport":{
"Interval":3000,
"ProtocolVersion":"v8",
"QueueSize":30000,
"BatchSize":3000,
"gRPC":{
"Servers":"192.168.3.245:11800",
"Timeout":10000,
"ConnectTimeout":10000,
"ReportTimeout":600000,
"Authentication":""
}
}
}
}

自動生成Skyapm.json

安裝CLI(SkyAPM.DotNet.CLI)

dotnet tool install -g SkyAPM.DotNet.CLI

自動生成skyapm.json檔案
server name指的就是您剛才配置的SKYWALKING__SERVICENAME,server指的是您Skywalking的ip地址。執行命令後,會自動生成一個skywalking.json 。

dotnet skyapm config [service name] [server]:11800

#eg: dotnet skyapm config MySkyWalking_OrderService 192.168.3.245:11800

SkyAPM Config 配置說明
ServiceName
服務名稱
Sampling
取樣配置節點
  • SamplePer3Secs 每3秒取樣數
  • Percentage 取樣百分比,例如10%取樣則配置為10
Logging
日誌配置節點
  • Level 日誌級別
  • FilePath 日誌儲存路徑
Transport
傳輸配置節點
  • Interval 每多少毫秒重新整理
  • gRPC

    gRPC配置節點
  • Servers gRPC地址,多個用逗號“,”
  • Timeout 建立gRPC連結的超時時間,毫秒
  • ConnectTimeout gRPC最長連結時間,毫秒

launchSettings.json檔案配置SK

"profiles":{// 專案
"IIS Express":{// IIS部署項
"commandName":"IISExpress",
"launchBrowser":true,
"launchUrl":"weatherforecast",
"environmentVariables":{
"ASPNETCORE_ENVIRONMENT":"Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES":"SkyAPM.Agent.AspNetCore",
"SKYWALKING__SERVICENAME":"MySkyWalkingDemoTest"
}
},
"SkyWalkingDemo":{// castrol部署項
"commandName":"Project",
"launchBrowser":true,
"launchUrl":"weatherforecast",
"applicationUrl":"http://localhost:5000",
"environmentVariables":{
"ASPNETCORE_ENVIRONMENT":"Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES":"SkyAPM.Agent.AspNetCore",// 必須配置
"SKYWALKING__SERVICENAME":"MySkyWalkingDemoTest"// 必須配置,在skywalking做標識
}
}
}

startup.cs檔案中新增

public

voidConfigureServices(IServiceCollection services)

{

services.AddSkyApmExtensions();

// 新增Skywalking相關配置

services.AddControllers();

services.AddHttpClient();

}

獲取traceId

private readonly IEntrySegmentContextAccessor segContext;
public

SkywalkingController(IEntrySegmentContextAccessor segContext)

{

this.segContext = segContext;

}

/// <summary>
/// 獲取連結追蹤ID
/// </summary>
/// <returns></returns>

[HttpGet(

"traceId"

)]

public

stringGetSkywalkingTraceId()

{

return

segContext.Context.TraceId;

}

自定義呼叫鏈路的資訊

[HttpGet]

public async Task<IActionResult>

SkywalkingTest()

{

//獲取全域性的skywalking的TracId

var TraceId = _segContext.Context.TraceId;

Console.WriteLine($

"TraceId={TraceId}"

);

_segContext.Context.Span.AddLog(LogEvent.Message($

"SkywalkingTest---Worker running at: {DateTime.Now}"

));
System.Threading.Thread.Sleep(

1000

);
_segContext.Context.Span.AddLog(LogEvent.Message($

"SkywalkingTest---Worker running at--end: {DateTime.Now}"

));

return

Ok($

"Ok,SkywalkingTest-TraceId={TraceId} "

);

}

接入微服務閘道器+後臺微服務

閘道器接入

新增依賴

<ItemGroup>
<PackageReferenceInclude="SkyAPM.Agent.AspNetCore"Version="1.3.0" />
</ItemGroup>

複製配置檔案並簡單修改

{
"SkyWalking":{
"ServiceName":"MySkyWalking_Gateway",

#修改名稱就OK

"Namespace":"",
"HeaderVersions":[
"sw8"
],
"Sampling":{
"SamplePer3Secs":-1,
"Percentage":-1.0
},
"Logging":{
"Level":"Debug",
"FilePath":"logs\\skyapm-{Date}.log"
},
"Transport":{
"Interval":3000,
"ProtocolVersion":"v8",
"QueueSize":30000,
"BatchSize":3000,
"gRPC":{
"Servers":"192.168.3.245:11800",
"Timeout":10000,
"ConnectTimeout":10000,
"ReportTimeout":600000,
"Authentication":""
}
}
}
}

launchsettings.json新增環境變數

"profiles":{
"Zhaoxi.MicroService.GatewayCenter":{
"commandName":"Project",
"dotnetRunMessages":true,
"launchBrowser":true,
"launchUrl":"swagger",
"applicationUrl":"https://localhost:7141;http://localhost:5141",
"environmentVariables":{
"ASPNETCORE_ENVIRONMENT":"Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES":"SkyAPM.Agent.AspNetCore",

#新增HOST變數

"SKYWALKING__SERVICENAME":"MySkyWalking_Gateway"

#新增服務名稱

}
},
"IIS Express":{
"commandName":"IISExpress",
"launchBrowser":true,
"launchUrl":"swagger",
"environmentVariables":{
"ASPNETCORE_ENVIRONMENT":"Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES":"SkyAPM.Agent.AspNetCore",
"SKYWALKING__SERVICENAME":"MySkyWalking_Gateway"
}
}
}

修改閘道器配置檔案,新增OrderServiceInstance微服務的路由

{
"DownstreamPathTemplate":"/api/{url}",//服務地址--url變數
"DownstreamScheme":"http",
"UpstreamPathTemplate":"/microservice/{url}",//閘道器地址--url變數
"UpstreamHttpMethod":["Get","Post"],
"UseServiceDiscovery":true,
"ServiceName":"OrderService",//consul服務名稱
"LoadBalancerOptions":{
"Type":"RoundRobin"//輪詢
}

啟動閘道器

dotnet run --urls=http

://*:6299

訂單微服務接入

新增依賴

<ItemGroup>
<PackageReferenceInclude="SkyAPM.Agent.AspNetCore"Version="1.3.0" />
</ItemGroup>

複製配置檔案並簡單修改

{
"SkyWalking":{
"ServiceName":"MySkyWalking_OrderService",
"Namespace":"",
"HeaderVersions":[
"sw8"
],
"Sampling":{
"SamplePer3Secs":-1,
"Percentage":-1.0
},
"Logging":{
"Level":"Debug",
"FilePath":"logs\\skyapm-{Date}.log"
},
"Transport":{
"Interval":3000,
"ProtocolVersion":"v8",
"QueueSize":30000,
"BatchSize":3000,
"gRPC":{
"Servers":"192.168.3.245:11800",
"Timeout":10000,
"ConnectTimeout":10000,
"ReportTimeout":600000,
"Authentication":""
}
}
}
}

launchsettings.json新增環境變數

"profiles":{
"Zhaoxi.MicroService.OrderServiceInstance":{
"commandName":"Project",
"dotnetRunMessages":true,
"launchBrowser":true,
"launchUrl":"swagger",
"applicationUrl":"http://192.168.3.105:7900",
"environmentVariables":{
"ASPNETCORE_ENVIRONMENT":"Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES":"SkyAPM.Agent.AspNetCore",
"SKYWALKING__SERVICENAME":"MySkyWalking_OrderService"
}
},
"IIS Express":{
"commandName":"IISExpress",
"launchBrowser":true,
"launchUrl":"swagger",
"environmentVariables":{
"ASPNETCORE_ENVIRONMENT":"Development"
}
}
}

啟動訂單微服務

dotnet run

使用者微服務接入

步驟和訂單微服務一樣

配置Skywalking告警

配置告警規則

docker exec -it 12f053748e85 /bin/sh

ls -l

查閱配置規則檔案及配置規則解讀

透過cat alarm-settings.yml可以查閱檔案內容,如下:

docker cp 12f053748e85:/skywalking/config/alarm-settings.yml .

# 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

database_access_resp_time_rule:

metrics-name: database_access_resp_time

threshold: 1000

op: ">"

period: 10

count: 2

message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes

endpoint_relation_resp_time_rule:

metrics-name: endpoint_relation_resp_time

threshold: 1000

op: ">"

period: 10

count: 2

message: Response time of endpoint relation {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(Observability Analysis Language)指令碼中的度量名;名稱在SkyWalking後端服務中已經定義,進入容器skywalking-oap之後,進入如下目錄就可以找到。
include names

: 本規則告警生效的實體名稱,如服務名,終端名;

exclude-names

:將此規則作用於不匹配的實體名稱上,如服務名,終端名;

threshold

: 閾值,可以是一個數組,即可以配置多個值;

op

: 運算子, 可以設定 >, <, =;

period

: 多久檢查一次當前的指標資料是否符合告警規則;以分鐘為單位

count

: 超過閾值條件,達到

count

次數,觸發告警;

silence period

:在同一個週期,指定的

silence period

時間內,忽略相同的告警訊息;

更多告警規則詳情,請參照這個地址:https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/backend-alarm.md

修改告警規則

rules:

service_test_sal_rule:

# 指定指標名稱

metrics-name: service_test_sal

# 小於

op: "<"

# 指定閾值

threshold: 8000

# 每2分鐘檢測告警該規則

period: 2

# 觸發1次規則就告警

count: 1

# 設定三分鐘內容相同告警,不重複告警

silence-period: 3

# 配置告警資訊

message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes

概要:服務成功率在過去2分鐘內低於80%

告警API編寫

本質還是SkyWalking根據規則進行檢查,如果符合規則條件,就透過WebHook、gRPCHook、WeChat Hook、Dingtalk Hook等方式進行訊息通知;接收到告警資料資訊之後,可以自行處理訊息。這裡為了方便,就採用WebHook的方式進行演示,即觸發告警條件之後,SkyWalking會呼叫配置的WebHook 介面,並傳遞對應的告警資訊;
定義資料模型

public

classAlarmMsg

{

public

int

scopeId { get;

set

; }

public

string

? scope { get;

set

; }

public

string

? name { get;

set

; }

public

string

? id0 { get;

set

; }

public

string

? id1 { get;

set

; }

public

string

? ruleName { get;

set

; }

public

string

? alarmMessage { get;

set

; }

}

定義WebHook呼叫API
/// <summary>
/// 告警API
/// </summary>
/// <param name="msgs"></param>
/// <returns></returns>

[HttpPost(

"AlarmMsg"

)]

public

voidAlarmMsg(List<AlarmMsg> msgs)

{

string

msg =

"觸發告警:"

;

msg += msgs.FirstOrDefault()?.alarmMessage;

Console.WriteLine(msg);

SendMail(msg);

}

配置webHook

http://192.168.3.105:7900/api/Skywalking/AlarmMsg

# 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

database_access_resp_time_rule:

metrics-name: database_access_resp_time

threshold: 1000

op: ">"

period: 10

count: 2

message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes

endpoint_relation_resp_time_rule:

metrics-name: endpoint_relation_resp_time

threshold: 1000

op: ">"

period: 10

count: 2

message: Response time of endpoint relation {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://192.168.3.105:7900/api/Skywalking/AlarmMsg

# - http://127.0.0.1/go-wechat/

rules:

# 告警規則名稱,必須唯一,以_rule結尾

service_sla_rule:

# 指定metrics-name

metrics-name: service_sla

# 小於

op: "<"

# 指定閾值

threshold: 8000

# 10分鐘檢測一次告警規則

period: 10

# 觸發2次告警規則就告警

count: 2

# 設定的3分鐘時間段有相同的告警,不重複告警.

silence-period: 3

# 配置告警訊息

message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes

webhooks:

- http://192.168.3.105:7900/api/Skywalking/AlarmMsg

登峰造極的成就源於自律
連結:https://www.cnblogs.com/AJun816/p/16212441.html
                                                              (版權歸原作者所有,侵刪)

文末福利

即將步入2025年,不少小夥伴在考慮來年的工作方向。

僅目前來說,傳統運維衝擊年薪30W+的轉型方向就是SRE&DevOps崗位。

為了幫助大家早日擺脫繁瑣的基層運維工作,給大家整理了一套【2024最新運維資料高階運維工程師必備技能資料包(文末一鍵領取),內容有多詳實豐富看下圖!
共有 20 個模組
1.38張最全工程師技能圖譜
2.面試大禮包
3.Linux書籍
4.go書籍
······
6.自動化運維工具
18.訊息佇列合集
 以上所有資料獲取請掃碼
識別上方二維碼
備註:2024最新運維資料
100%免費領取
(是掃碼領取,不是在公眾號後臺回覆,別看錯了哦)


相關文章