別說不會微服務了,六分鐘教你巧妙玩轉分佈式下鏈路追蹤!

本篇文章我將給大家介紹“分佈式鏈路追蹤”的內容,對於目前大部分採用微服務架構的公司來說,分佈式鏈路追蹤都是必備的,無論它是傳統微服務體系亦或是新一代Service Mesh的微服務架構!而具體介紹的內容,本文不是完全講理論,而是希望從理論到實踐,引導大家去操作,因爲只有這樣才能真正從技術層面有深刻的認識和了解!

分佈式鏈路追蹤概述

在具體介紹分佈式鏈路追蹤系統之前,我們首先需要理解下什麼是鏈路追蹤?在本專欄前面關於監控系統的介紹中可以知道,監控系統的觀測數據主要來源於統計指標、日誌以及鏈路追蹤這三個方面。而這些數據從類型上又可以劃分爲兩種:請求級別、聚合級別

請求級別的數據主要來源於真實的請求,例如一次HTTP調用、RPC調用等,本文要介紹的鏈路追蹤就是這種類型。而聚合級別則是接口請求的度量指標或者一些參數數據的聚合,如QPS、CPU使用率等數值。日誌和統計指標數據既可以是請求級別,也可以是聚合級別,因爲它們可能來自源於真實的請求,也可能是系統自身診斷時記錄下來的信息。

對於鏈路追蹤來說,它主要的邏輯就是將請求鏈路的完整行爲記錄下來,以便可以通過可視化的形式實現鏈路查詢、性能分析、依賴關係、拓撲圖等分佈式鏈路追蹤相關的功能。如下圖所示:

在上圖中假設微服務系統中的一次接口調用總共有兩個微服務參與,其調用關係分別是A->B->C,其中B服務還與Redis這樣的第三方服務產生了調用關係、C服務則還需要調用MySQL數據庫服務。所以實際上鍊路追蹤所做的事情就是詳細記錄A->B(B->Redis)->C(C->MySQL)這條完整鏈路上的詳細調用信息,例如接口響應結果、耗時等。

那麼這條調用鏈路上的數據到底是怎樣被記錄的呢?接下來我們繼續以上面的調用鏈爲例分析下鏈路追蹤信息的具體組成和傳遞形式,以便進一步理解分佈式鏈路追蹤系統的原理和概念。具體邏輯示意圖如下:

如上圖所示,分佈式鏈路追蹤所監控的對象就是一次次調用所產生的鏈路,圖中1-8所示的就是一條完整的鏈路(Trace),系統會通過唯一的標識(TraceId)對此進行記錄。而鏈路中的每一個依賴調用都會生成一個調用蹤跡信息(Span),最開始生成的Span叫做根Span(Root Span),後續生成的Span都會將前一個Span 的標示(Sid)作爲本Span信息的父ID(Pid)。

這樣以此類推,Span信息就會隨着鏈路的執行被進程內或跨進程進行上下文傳遞,通過Span數據鏈就能將一次次鏈路調用所產生的蹤跡信息串聯起來,而每一個Span之上附着的日誌信息(Annotation)就是我們進行調用鏈監控分析的數據來源。這就是分佈式鏈路追蹤的基本原理

而說到這裏,你可能會有疑問:監控這麼大的數據量,是不是會很消耗系統資源?的確如此,所以大部分鏈路追蹤系統,都會存在一個叫做採樣率(Sampling)的設定,用來控制系統採集鏈路信息的比例,從而提升系統性能。因爲很多時候,大量的鏈路信息都是相同的,我們需要關注的可能也只是相對耗時較高、出錯次數較多的鏈路,而並沒有必要100%的進行採集。

SkyWalking簡介

前面我們從基本原理的角度說明了鏈路追蹤是什麼,那麼接下來我們將介紹下目前最流行的分佈式鏈路追蹤系統——SkyWalking。

SkyWalking是一款優秀的開源APM(Application Performance Management)系統,它不僅提供了鏈路追蹤,鏈路分析等分佈式追蹤功能,還支持性能指標分析、應用和服務依賴性分析、服務拓撲圖分析、報警等一系列應用性能監控相關的功能,可以幫助我們有效地定位問題。

而從數據收集上看,SkyWalking支持多種不同的數據來源及格式,包括支持Java、.NET Core、NodeJS、PHP和Python等不同語言的無侵入式Agent探針,以及對Service Mesh(服務網格)架構的支持等。其具體結構如下圖所示:

如上圖所示,SkyWalking的核心由鏈路收集服務器(Receiver Cluster)、聚合服務器(AggregatorCluster)組成。其中Receiver Cluster是整個後端服務接入的入口,專門用於收集服務的各種指標及鏈路信息。

而AggregatorCluster則用於彙總、聚合收集器收集到的數據,並最終將聚合數據存儲到數據庫中,而具體存儲方式可以有多種,例如常見的ElasticSearch、MySQL、TIDB等,我們可以根據實際需要進行選擇。這些聚合數據後面可以用於告警設置,也可以被GUI/CLI等可視化系統以HTTP的形式訪問後進行可視化展示。

此外,從數據採集邏輯上看,SkyWalking支持多種語言探針及項目協議,能夠覆蓋目前大部分主流的分佈式技術棧,具體來說主要有以下3種:

  • Metrics System:統計系統。支持直接從Prometheus中拉取度量指標數據到SkyWalking,也支持程序自身通過micrometer推送數據;

  • Agents:業務探針。指在各個業務系統中集成探針服務來進行鏈路追蹤,即鏈路數據採集。SkyWalking支持Java、Go、.NET、PHP、NodeJS、Python、Nginx LUA等多種語言的探針。此外,它還支持通過gRPC或者HTTP的方式來傳遞數據;

  • Service Mesh:SkyWalking還支持對新一代微服務架構Service Mesh的監控,可以通過特定的Service Mesh協議採集數據面、控制面的數據,實現對服務網格鏈路數據的觀測;

上面的內容簡單介紹了SkyWalking的基本情況,並就其系統架構進行了簡單分析。實際上SkyWalking最近兩年發展得非常快,社區也非常活躍,在微服務鏈路追蹤、應用性能監控領域被使用得也越來越廣泛,由於篇幅原因,這裏無法進行更深入的分享,感興趣的讀者可以通過官方文檔或社區進行深入瞭解!

SkyWalking安裝部署

前面的內容分別介紹了分佈式鏈路追蹤的基本原理,並着重介紹了SkyWalking!很顯然,寫到這裏就結束的話,本文就沒有啥價值了,因爲只是說了一堆正確的廢話,看了也就忘了!這顯然也不符合我分享的風格,接下來我們就從實驗的角度來玩一下SkyWalking。

以下內容需要進行實際實驗操作,如果在地鐵上不方便可以先收藏,有時間再具體實驗玩下!

對於SkyWalking的部署主要涉及到後端OAP Server和前端UI,根據實際需要可以將它們部署在物理機虛擬機或者Kubernetes集羣之中。這裏爲了演示環境的一致性,我們選擇將SkyWalking的後端服務及UI分別部署到Kubernetes集羣中。

而具體安裝SkyWalking的方式可以通過官方提供的Kubernetes部署文件採用Helm方式安裝,也可以手動編寫Kubernetes部署文件,這裏爲了便於學習,我們採用後一種方式。具體步驟如下:

1)、在Kubernetes集羣中創建一個單獨運行SkyWalking容器的Namespace。命令如下:

#通過kubectl連接Kubernetes集羣后執行,創建namespace命令
$ kubectl create ns skywalking

命令執行完成後,可以查看Namespace是否創建成功,命令如下:

#查看namespace創建情況
$ kubectl get ns
NAME                   STATUS   AGE
default                Active   10d
kube-node-lease        Active   10d
kube-public            Active   10d
kube-system            Active   10d
kubernetes-dashboard   Active   10d
skywalking             Active   46s

可以看到此時skywalking空間已經成功創建!

2)、編寫SkyWalking-UI及OAP Server服務Kubernetes部署文件

在編寫具體的Kubernetes部署文件的過程中需要指定SkyWalking-UI及OAP Server的容器鏡像,一般來說可以通過源碼手動打包也可以直接使用官方已經打包好的鏡像。這裏爲了方便演示,採用Docker官方鏡像倉庫中已經打包好的鏡像。具體如圖所示:

如果上面兩張圖所示,我們分別在Docker Hub官方鏡像倉庫中找到了SkyWalking-UI及OAP Server的官方發佈的容器鏡像版本,接下來編寫具體的部署文件。

編寫SkyWalking服務端Kubernetes部署文件(skywalking-aop.yml),具體內容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: oap
  namespace: skywalking
spec:
  replicas: 1
  selector:
    matchLabels:
      app: oap
      release: skywalking
  template:
    metadata:
      labels:
        app: oap
        release: skywalking
    spec:
      containers:
        - name: oap
          #指定OAP Server容器鏡像及版本信息
          image: apache/skywalking-oap-server:8.3.0-es7
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 11800
              name: grpc
            - containerPort: 12800
              name: rest
---
apiVersion: v1
kind: Service
metadata:
  name: oap
  namespace: skywalking
  labels:
    service: oap
spec:
  ports:
    #restful端口
    - port: 12800
name: rest
     #rpc端口
    - port: 11800
      name: grpc
    - port: 1234
      name: page
  selector:
    app: oap

以上是一個標準的Kubernetes部署文件,關於文件中相關指令的具體含義可查閱Kubernetes相關的資料。

編寫SkyWalking-UI部署文件(skywalking-ui.yml),具體內容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ui-deployment
  namespace: skywalking
  labels:
    app: ui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ui
  template:
    metadata:
      labels:
        app: ui
    spec:
      containers:
        - name: ui
          image: apache/skywalking-ui:8.3.0
          ports:
            - containerPort: 8080
              name: page
          env:
            - name: SW_OAP_ADDRESS
              value: oap:12800
---
apiVersion: v1
kind: Service
metadata:
  name: ui
  namespace: skywalking
  labels:
    service: ui
spec:
  ports:
    - port: 8080
      name: page
      nodePort: 31234
  type: NodePort
  selector:
    app: ui

3)、根據編寫的部署文件,執行Kubernetes部署命令

根據前面步驟中編寫的Kubernetes發佈文件,這裏我們根據編寫的發佈文件直接執行部署命令,具體如下:

#進入發佈文件的存儲目錄,直接一次性執行全部文件部署命令
$ kubectl apply -f .
deployment.apps/oap created
service/oap created
deployment.apps/ui-deployment created
service/ui created

執行完成後通過命令查看具體部署的情況,命令如下:

#查看skywalking空間中的Pod、Service對象的運行情況
$ kubectl get all -n skywalking
NAME                                 READY   STATUS    RESTARTS   AGE
pod/oap-5f6d6bc4f6-k4mvv             1/1     Running   0          36h
pod/ui-deployment-868c66449d-fffrt   1/1     Running   0          36h

NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                        AGE
service/oap   ClusterIP   10.110.112.244   <none>        12800/TCP,11800/TCP,1234/TCP   36h
service/ui    NodePort    10.100.154.93    <none>        8080:31234/TCP                 36h

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/oap             1/1     1            1           36h
deployment.apps/ui-deployment   1/1     1            1           36h

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/oap-5f6d6bc4f6             1         1         1       36h
replicaset.apps/ui-deployment-868c66449d   1         1         1       36h

可以看到部署的SkyWalking服務都已經正常運行!如果是第一次部署,拉取鏡像的過程可能會比較慢一點。如果在部署過程中存在問題,也可以查看Pod對象的運行日誌,例如:

#可以查看aop的啓動日誌
$ kubectl logs pod/oap-5f6d6bc4f6-k4mvv -n skywalking

4)、查看SkyWalking-UI的Web訪問地址

經過上述步驟,我們已經成功將SkyWalking-UI、OAP Server兩個服務運行在Kubernetes集羣之中。接下來通過SkyWalking-UI服務的映射端口(k8s部署文件中定義是31234端口)訪問Web UI,具體可通過http://NodeIP:31234進行訪問,例如:

#這裏的IP爲Kubernetes集羣向外暴露的節點入口IP
http://10.211.55.12:31234/ 

如果不知道Kubernetes集羣節點入口IP地址,可以通過以下命令進行查看:

#查詢SkyWalking-UI所部署的Kubernetes集羣Node節點的IP地址
$ kubectl describe node kubernetes
Name:               kubernetes
Roles:              master
...
Addresses:
  InternalIP:  10.211.55.12
  Hostname:    kubernetes
...

訪問後的界面顯示效果如下圖所示:

如上圖所示,此時可以看到SkyWalking已成功運行,由於尚無服務接入所以暫時還看不到有任何監控數據!

後記

如前面所述內容我們已經在Kubernetes環境中將分佈式鏈路追蹤系統部署成功了,另外由於還沒有服務接入所以暫時還看不到任何鏈路追蹤數據,但是由於篇幅的原因這裏就不繼續介紹如何將Java微服務接入SkyWalking了,但是這個這個接入過程卻是非常有意思的,因爲它是我們作爲研發人員,進一步理解微服務程序與分佈式鏈路追蹤系統集成、交互的關鍵!這部分我將作爲續集在下一篇文章中給大家分享,時間不會太久,期待大家保持關注!

寫在最後

歡迎大家關注我的公衆號【風平浪靜如碼】,海量Java相關文章,學習資料都會在裏面更新,整理的資料也會放在裏面。

覺得寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章