通過 Dapr 實現一個簡單的基於 dotnet 的微服務電商系統——一步一步教你如何擼 Dapr 之鏈路追蹤

Dapr 提供了一些開箱即用的分佈式鏈路追蹤解決方案,今天我們來講一講如何通過 dapr 的 configuration 來實現非侵入式鏈路追蹤的

目錄:

一、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統

二、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統 (二)——通訊框架講解

三、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統 (三)——一步一步教你如何擼 Dapr

四、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統 (四)——一步一步教你如何擼 Dapr 之訂閱發佈

五、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統 (五)——一步一步教你如何擼 Dapr 之狀態管理

六、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統 (六)——一步一步教你如何擼 Dapr 之 Actor 服務

[七、通過 Dapr 實現一個簡單的基於. net 的微服務電商系統 (七)——一步一步教你如何擼 Dapr 之服務限流]](https://www.readfog.com/a/1634023379212275712)

附錄:(如果你覺得對你有用,請給個 star)
一、電商 Demo 地址:https://github.com/sd797994/Oxygen-Dapr.EshopSample_

二、通訊框架地址:https://github.com/sd797994/Oxygen-Dapr

  首先依然簡單聊聊什麼是鏈路追蹤以及我們爲什麼需要它, 知道鏈路追蹤的同學可以跳過。在傳統的單體應用中,我們的每一次請求往往在同一個進程中被一次性處理。而在分佈式系統中,我們需要通過不同容器隔離甚至物理機隔離的服務間協同作業來實現某些業務,同時由於業務流轉會涉及到接口調用、事件訂閱、狀態讀寫、actor 調用等等情況,往往想要追蹤它們形成一個鏈式調用的記錄會比較困難。這裏舉一個例子,某分佈式系統集羣運行在生產環境上,某日收到預警某接口調用非常緩慢。這個時候開發人員排查發現該聚合網關接口調用了服務 A、B、C 但是不知道具體是哪個服務導致的緩慢,通知 A、B、C 對應的開發組人員通過本地調試發現 A、B、調用正常,C 緩慢,但是 C 發現並非由於自身業務邏輯緩慢,而是自己調用 D 時返回比較緩慢,這時又只得通知 D 負責的團隊進行業務排查,最終 D 發現自己的代碼問題,然後逐一修復併發布到生產環境解決該問題。這個例子比較極端哈,這裏僅舉個例子說明。鏈路追蹤系統就是幫助分佈式系統在鏈路調用時記錄每一個接口的響應時間以及自己依賴的下游接口的響應時間並提供可視化 UI 方便開發運維團隊快速排查接口調用耗時異常定位問題。

  傳統的鏈路追蹤一般是通過代碼侵入式的方式由開發人員集成 SDK 插入代理,應用上線運行後這些代理即可自動化監視我們的應用進程記錄流量流入、流出請求 / 響應時間並統一上報到鏈路追蹤系統,而 service mesh 由於 sidecar 的存在可以確保流量在流入 / 流出應用時一定會經過 sidecar,所以天生更容易實現鏈路追蹤,從而免於讓開發人員人工通過 SDK 的方式去集成一個分佈式鏈路追蹤系統,接下來就講講我們在 dapr 下如何來實現它。

  首先我們需要在 k8s 環境跑起來一個鏈路追蹤系統,大家可以看看這裏:https://docs.dapr.io/operations/monitoring/tracing/supported-tracing-backends/ 是目前 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。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/dX-2w040L3COFYKcwBGEVw