.NET Core 微服務—API閘道器(Ocelot) 教程 [四]

cwsheng發表於2020-08-09

前言:

  上一篇 介紹了Ocelot閘道器和認證服務的結合使用,本篇繼續介紹Ocelot相關請求聚合和Ocelot限流

一、請求聚合

  Ocelot允許宣告聚合路由,這樣可以把多個正常的Routes打包並對映到一個物件來對客戶端的請求進行響應。

  例如:在獲取訂單記錄時,也需要檢視訂單中對應的商品資訊,這裡的資料就來源於兩個微服務:訂單服務、商品服務。如果不使用聚合路由時,對於現實一個訂單資訊時,客戶端需要呼叫兩次服務請求,實際上會造成服務端額外的效能消耗。這是如果配置了聚合路由時,客戶端只需要請求一次聚合路由,然後聚合路由會合並訂單服務和商品服務的請求結果到一個物件中,並返回給客戶端。使用Ocelot的此特性可以讓你很容易的實現前後端分離的架構。接下來我們就來驗證該功能的實現。

  在ocelot.json中進行如下配置:

   1、為每個Route設定一個Key屬性:如:"Key": "Catalog"

   2、在ocelot.json中新增Aggregates節點,並指定RouteKeys中指定1中設定的Key值組成的陣列,並設定UpstreamPathTemplate匹配上游使用者請求;它的工作方式和正常的Route類似。

   調整後如下:

{
  "Aggregates": [
    {
      "RouteKeys": [
        "Catalog",
        "Ordering"
      ],
      "UpstreamPathTemplate": "/GetOrderDetail/{id}"
    }
  ],
  "GlobalConfiguration": {

  },
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/Values/{id}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5332
        }
      ],
      "UpstreamPathTemplate": "/Catalog/{id}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      "Key": "Catalog"
    },
    {
      "DownstreamPathTemplate": "/api/Values/{id}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5331
        }
      ],
      "UpstreamPathTemplate": "/Ordering/{id}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      "Key": "Ordering"
    }
  ]
}

   3、如圖調整專案程式碼:返回不同結果

    

 

 

   4、訪問設定的聚合地址結果如下:

    返回結果為設定的Key組合的資料結構。

    

 

 

   5、如果服務出現異常會怎麼樣:

   a) 如果當某個服務出現異常會返回什麼呢?接下來做個驗證,修改訂單服務返回結果:

 public IActionResult Get(int id)
 {
      throw new Exception("模擬異常");
 }

    

 

 

     如圖所示返回的結果和正常是結構是相同的,只是Ordering返回的是異常資訊;

   b) 如果某個服務當機,回得到什麼結果呢?接下來停止了Ordering服務訪問結果如下,得到502錯誤

    

 

  6、如果預設的聚合返回的結果資料結構不是我們想要的,想要修改怎麼辦?答案是使用自定義聚合

   a)新增一個自動以聚合器FakeDefinedAggregator, 必須實現IDefinedAggregator介面。這個聚合器的功能很簡單,就是將兩個聚合請求的結果,用逗號拼接起來返回

    public class FakeDefinedAggregator : IDefinedAggregator
    {
        public FakeDefinedAggregator()
        {
        }
        public async Task<DownstreamResponse> Aggregate(List<HttpContext> responses)
        {

            List<string> result = new List<string>();
            foreach (var item in responses)
            {
                byte[] tmp = new byte[item.Response.Body.Length];
                await item.Response.Body.ReadAsync(tmp, 0, tmp.Length);
                var val = Encoding.UTF8.GetString(tmp);
                result.Add(val);
            }
            var merge = string.Join(";", result.ToArray());
            List<Header> headers = new List<Header>();
            return new DownstreamResponse(new StringContent(merge), HttpStatusCode.OK, headers, "some reason");
        }
    }

 

   b)註冊自定義聚合器

services.AddOcelot()
        .AddSingletonDefinedAggregator<FakeDefinedAggregator>();

   c)修改ocelot.json配置檔案

"Aggregates": [
    {
      "ReRouteKeys": [
        "Orders",
        "Products"
      ],
      "UpstreamPathTemplate": "/GetOrderDetail/{id}",
"Aggregator": "FakeDefinedAggregator" } ]

   d)執行結果:

{"id":1,"name":"Api.Catalog1"};{"id":1,"name":"Api.Ordering"}}

二、限流

  1、修改Route節點中的新增如下節點:

 "RateLimitOptions": {
        "ClientWhitelist": [],
        "EnableRateLimiting": true,
        "Period": "10m",
        "PeriodTimespan": 3,
        "Limit": 1
}

  2、在GlobalConfiguration新增如下節點:

 //限流
    "RateLimitOptions": {
      "QuotaExceededMessage": "您的請求量超過了配額1/10分鐘",
      "HttpStatusCode": 999
}

  3、配置說明:

在Route和GlobalConfiguration節點中新增了RateLimitOptions節點
ClientWhitelist - 白名單,也就是不受限流控制的客戶端
EnableRateLimiting - 是否開啟限流
Period & Limit - 在一段時間內允許的請求次數
PeriodTimespan - 客戶端的重試間隔數,也就是客戶端間隔多長時間可以重試
QuotaExceededMessage - 限流以後的提示資訊
HttpStatusCode - 超出配額時,返回的http狀態碼

  4、配置說明:

    客戶端在10分鐘之內只允許請求一次,在請求之後3秒鐘之後可以重試

總結:

  1、請求聚合需要為每個Route設定一個Key,並設定Aggregates節點指定需要的RouteKeys。

  2、請求聚合支援自定義設定返回結果:實現IDefinedAggregator介面,並註冊自定義聚合器;

  3、在需要對伺服器請求進行限流時,Ocelot也能很好的支援

後續:

  後續將對Consul介紹,並結合Ocelot使用。

相關文章