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

  在一般的互聯網應用中限流是一個比較常見的場景,也有很多常見的方式可以實現對應用的限流比如通過令牌桶通過滑動窗口等等方式都可以實現,也可以在整個請求流程中進行限流比如客戶端限流就是在客戶端通過隨機數直接返回成功失敗來決定是否發起請求。也可以在網關層直接根據一定策略丟棄一部分流量達到限流的目的,亦可請求到業務端後由業務端判斷是否進行限流。而一般的 service mesh 框架會在代理的 sidecar 部分完成限流的工作。今天就講講 dapr 是如何通過簡易的配置來實現一個限流的。

目錄:

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

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

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

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

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

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

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

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

  Dapr 限流包含兩種模式,一種是客戶端限流,一種是服務端限流。

  客戶端限流簡單來講就是對下游服務的一種限流保護,舉個例子比如我的網關要保護後面的所有服務,我可以配置一個 ratelimit 的 component 下游限流注入到網關的 sidecar 中,Dapr 會爲流經該網關實例的流量的下游服務根據遠程 IP 和路徑進行限流,確保單位時間內最大請求數被限制在規定範圍之內。

   下面我們就來模擬這種限流模式,首先我們創建一個類型爲 middleware.http.ratelimit 的 Component,其 metadata 可以設置一個 maxRequestsPerSecond 參數,代表每秒流經該 sidecar 的請求最大能通過多少前往下游服務。如果超出這個請求,則 sidecar 會直接返回一個 429 響應碼提示客戶端請求過多

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: ratelimit
spec:
  type: middleware.http.ratelimit
  version: v1
  metadata:
  - name: maxRequestsPerSecond
    value: 1

  接着我們配置一個 Configuration 並注入到 clientsample 的 deployment 中 (注意紅字部分)

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  httpPipeline:
    handlers:
    - name: ratelimit
      type: middleware.http.ratelimit
apiVersion: apps/v1
kind: Deployment
metadata:
  name: clientsample
  labels:
    app: clientsample
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: clientsample
  template: 
    metadata:
      labels: 
        app: clientsample
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "clientsample"
        dapr.io/app-port: "80"
        dapr.io/config: "appconfig"
    spec:
      containers:
        - name: web
          image: clientsample:release
          imagePullPolicy: Never
          ports:
            - containerPort: 80

  現在我們在代碼中,讓 clientsample 通過多現成同時發起 10 個下游請求

        public async Task<dynamic> Call()
        {
            var result1 = new OutDto();
            var remoteService = serviceProxyFactory.CreateProxy<IHelloService>();
            var tasks = new Task<OutDto>[10];
            for (int i = 0; i < 10; i++)
            {
                tasks[i] = remoteService.HelloWorldByName(new InputDto() { Name = "xiaoming" });
            }
            await Task.WhenAll(tasks);
            foreach (var item in tasks)
            {
                Console.WriteLine($"result is :{(item.GetAwaiter().GetResult().Word ?? "noresult")}");
            }
            return "操作完成";
        }

  可以看到併發訪問 10 條 task,只有 1 條返回了 result,其餘的請求發送到自己的 sidecar 後就直接返回 429 然後被通訊框架捕獲 429 後拋到日誌中。

  接下來我們看看服務端模式,服務端模式顧名思義就是保護自己,確保所有流向自己的請求會以一個限定頻率被處理, 有點類似於 C# 的 semaphore,通過信號量來阻塞線程併發訪問數。注意該模式並不是通過限制每秒流量來實現的,而是指同時只能有多個請求被處理。

  接着我們看看 yaml 需要調整的部分,通過 dapr.io/app-max-concurrency 參數即可實現併發數控制

apiVersion: apps/v1
kind: Deployment
metadata:
  name: servicesample
  labels:
    app: servicesample
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: servicesample
  template: 
    metadata:
      labels: 
        app: servicesample
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "servicesample"
        dapr.io/app-port: "80"
        dapr.io/app-max-concurrency: "1"
    spec:
      containers:
        - name: web
          image: servicesample:release
          imagePullPolicy: Never
          ports:
            - containerPort: 80

  clientsample 不用修改,我們在 servicesample 的方法中增加以下模擬耗時操作

  重新生成後(注意需要刪除之前配置在 clientsample 上的 dapr.io/config),我們通過 postman 模擬發起請求:

  可以看到請求全部都執行成功並獲取回調了,但是整個請求耗時是 10 秒,恰好就是一次處理 1 個請求,單個請求耗時 1 秒得到的結果,我們可以再次驗證一下將 app-max-concurrency 設置爲 2,應該會 5 秒請求完畢:

  可以看到信號量每次放入了兩個線程同步處理,我們的請求確實被壓縮到了 5 秒處理完畢。

  整個限流其實分爲下游限流 + 併發控制兩種方式,其實都是爲了保護自己 / 下游服務。另外大家注意一下如果你的請求並不是通過 sidecar 進入到服務的比如直接暴露服務端口到 network 或通過 ingress+service 的方式訪問應用也就是說流量不走 sidecar,則無法通過 dapr 進行限流!關於限流今天就到這,下次分享一下如何做鏈路監控~

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s?__biz=MjM5MTc4MDM1MQ==&amp;mid=2651733942&amp;idx=1&amp;sn=bd56e527dd18648486d7718a098ef649&amp;chksm=bd4ac3268a3d4a30b45e71db152a674e9e436cb03242ccf911e61fb8f27ebf428f51ab568d57&amp;scene=178&amp;cur_album_id=1800637212208742405#rd