Dapr提供了一些開箱即用的分散式鏈路追蹤解決方案,今天我們來講一講如何通過dapr的configuration來實現非侵入式鏈路追蹤的
目錄:
一、通過Dapr實現一個簡單的基於.net的微服務電商系統
二、通過Dapr實現一個簡單的基於.net的微服務電商系統(二)——通訊框架講解
三、通過Dapr實現一個簡單的基於.net的微服務電商系統(三)——一步一步教你如何擼Dapr
四、通過Dapr實現一個簡單的基於.net的微服務電商系統(四)——一步一步教你如何擼Dapr之訂閱釋出
五、通過Dapr實現一個簡單的基於.net的微服務電商系統(五)——一步一步教你如何擼Dapr之狀態管理
六、通過Dapr實現一個簡單的基於.net的微服務電商系統(六)——一步一步教你如何擼Dapr之Actor服務
七、通過Dapr實現一個簡單的基於.net的微服務電商系統(七)——一步一步教你如何擼Dapr之服務限流
八、通過Dapr實現一個簡單的基於.net的微服務電商系統(八)——一步一步教你如何擼Dapr之鏈路追蹤
附錄:(如果你覺得對你有用,請給個star)
一、電商Demo地址
首先依然簡單聊聊什麼是鏈路追蹤以及我們為什麼需要它,知道鏈路追蹤的同學可以跳過。在傳統的單體應用中,我們的每一次請求往往在同一個程式中被一次性處理。而在分散式系統中,我們需要通過不同容器隔離甚至物理機隔離的服務間協同作業來實現某些業務,同時由於業務流轉會涉及到介面呼叫、事件訂閱、狀態讀寫、actor呼叫等等情況,往往想要追蹤它們形成一個鏈式呼叫的記錄會比較困難。這裡舉一個例子,某分散式系統叢集執行在生產環境上,某日收到預警某介面呼叫非常緩慢。這個時候開發人員排查發現該聚合閘道器介面呼叫了服務A、B、C但是不知道具體是哪個服務導致的緩慢,通知A、B、C對應的開發組人員通過本地除錯發現A、B、呼叫正常,C緩慢,但是C發現並非由於自身業務邏輯緩慢,而是自己呼叫D時返回比較緩慢,這時又只得通知D負責的團隊進行業務排查,最終D發現自己的程式碼問題,然後逐一修復併發布到生產環境解決該問題。這個例子比較極端哈,這裡僅舉個例子說明。鏈路追蹤系統就是幫助分散式系統在鏈路呼叫時記錄每一個介面的響應時間以及自己依賴的下游介面的響應時間並提供視覺化UI方便開發運維團隊快速排查介面呼叫耗時異常定位問題。
傳統的鏈路追蹤一般是通過程式碼侵入式的方式由開發人員整合SDK插入代理,應用上線執行後這些代理即可自動化監視我們的應用程式記錄流量流入、流出請求/響應時間並統一上報到鏈路追蹤系統,而service mesh由於sidecar的存在可以確保流量在流入/流出應用時一定會經過sidecar,所以天生更容易實現鏈路追蹤,從而免於讓開發人員人工通過SDK的方式去整合一個分散式鏈路追蹤系統,接下來就講講我們在dapr下如何來實現它。
首先我們需要在k8s環境跑起來一個鏈路追蹤系統,大家可以看看這裡是目前dapr支援的鏈路後端,我這裡就選型我比較熟悉的zipkin來實現。zip在k8s中很容易跑起來,這是yaml:
--- apiVersion: apps/v1 kind: Deployment metadata: name: zipkin spec: selector: matchLabels: app: zipkin replicas: 1 template: metadata: labels: app: zipkin spec: containers: - name: zipkin image: openzipkin/zipkin:latest imagePullPolicy: IfNotPresent ports: - containerPort: 9411 env: - name: TZ value: "Asia/Shanghai" --- apiVersion: v1 kind: Service metadata: name: zipkin spec: type: NodePort selector: app: zipkin ports: - protocol: TCP port: 9411 targetPort: 9411
由於需要在本地訪問zip的website,我這裡偷懶直接將nodeport暴露到本地k8s叢集,方便等會兒通過瀏覽器訪問。現在我們apply一下,稍微等待一段時間k8s拉取映象並執行起來後,通過kubectl get svc 查詢zipkin暴露的隨機埠即可通過localhost:nodeport訪問到zipkin的介面:
接下來就比較簡單了,我們建立一個型別為configuration的配置檔案,並注入到每一個需要追蹤的服務即可,其中samplingRate是指取樣率,而endpointAddress是指我們在k8s叢集內通過svc能訪問到的zipkin的地址(如果你的zipkin部署在非本叢集,則可通過ip or 網址的方式訪問):
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: zipkin spec: metric: enabled: true tracing: samplingRate: "1" zipkin: endpointAddress: "http://zipkin.infrastructure.svc.cluster.local:9411/api/v2/spans"
接著我們將這個configuration注入到我們需要的服務中,這裡我們直接看電商demo yaml檔案賬戶服務的情況(紅字部分):
apiVersion: apps/v1 kind: Deployment metadata: name: accountservice namespace: dapreshop labels: app: accountservice spec: replicas: 1 selector: matchLabels: app: accountservice minReadySeconds: 5 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 template: metadata: labels: app: accountservice version: v1 annotations: dapr.io/enabled: "true" dapr.io/app-id: "accountservice" dapr.io/app-port: "80" dapr.io/config: "zipkin" spec: containers: - name: web image: accountservice:release imagePullPolicy: Never readinessProbe: httpGet: path: v1.0/healthz port: 3500 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds : 5 failureThreshold : 3 ports: - containerPort: 80
現在我們來下單看看,訪問admin.dapreshop.com:30882,初始化系統後,訪問m.dapreshop.com:30882,下單一次。接著開啟我們的zipkin,查詢run query即可看到最新一條鏈路追蹤記錄如下:
可以看到鏈路追蹤的root是我們的apigateway,因為客戶端請求是從這裡被聚合的。接著apigateway會呼叫商品服務、交易服務、使用者服務、以及作業系統。這裡我們再看看我們的程式碼看看createorder明細:
這個用例服務會呼叫使用者服務獲取一個mockaccount模擬使用者用於下單,接著會呼叫一個建立訂單的領域服務用於下單這裡會呼叫商品的actor服務用於原子減扣庫存(此部分可參考之前的actor文章),下單完成後會傳送一個訂單建立成功事件,由作業系統訂閱並等待5分鐘後進行未支付訂單取消操作,整個下單流程如下:
整個流程相對比較簡單,通過在daprd sidecar上申明瞭zipkin configuration後 daprd會忠實的將我們的請求轉化為鏈路追蹤記錄並上報zipkin,我們點開zipkin那條記錄檢視明細如下:
可以非常清楚的看到我們的訂單建立呼叫的賬戶服務的mockaccount介面,然後呼叫了商品服務的商品資訊介面,接著呼叫數個商品actor進行庫存減扣,最終持久化我們的訂單後發起一個事件並且成功的被作業系統訂閱。每一個介面請求了多少時間被清楚的記錄了下來,這樣在生產環境下就很容易排除慢介面的問題而不用像上面提到的那樣各個團隊忙的焦頭爛額了
dapr目前還提供了其他的一些鏈路追蹤客戶端,但是整體大的流程基本如本文所述,今天的分享就到這裡,希望大家多多支援dapr,多多轉發fork+star。下一次我們將分享一下如何整合一個第三方的oauth授權服務來實現oauth。