Ocelot簡易教程(四)之請求聚合以及服務發現

来源:https://www.cnblogs.com/yilezhu/archive/2018/09/24/9695639.html
-Advertisement-
Play Games

Ocelot簡易教程(四)之請求聚合以及服務發現 上篇文章給大家講解了Ocelot的一些特性並對路由進行了詳細的介紹,今天呢就大家一起來學習下Ocelot的請求聚合以及服務發現功能。希望能對大家有所幫助。 作者:依樂祝 原文地址:https://www.cnblogs.com/yilezhu/p/9 ...


Ocelot簡易教程(四)之請求聚合以及服務發現

上篇文章給大家講解了Ocelot的一些特性並對路由進行了詳細的介紹,今天呢就大家一起來學習下Ocelot的請求聚合以及服務發現功能。希望能對大家有所幫助。

作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/9695639.html

請求聚合

Ocelot允許你聲明聚合路由,這樣你可以把多個正常的ReRoutes打包並映射到一個對象來對客戶端的請求進行響應。比如,你請求訂單信息,訂單中又包含商品信息,這裡就設計到兩個微服務,一個是商品服務,一個是訂單服務。如果不運用聚合路由的話,對於一個訂單信息,客戶端可能需要請求兩次服務端。實際上這會造成服務端額外的開銷。這時候有了聚合路由後,你只需要請求一次聚合路由,然後聚合路由會合併訂單跟商品的結果都一個對象中,並把這個對象響應給客戶端。使用Ocelot的此特性可以讓你很容易的實現前後端分離的架構。
為了實現Ocelot的請求功能,你需要在ocelot.json中進行如下的配置。這裡我們指定了了兩個正常的ReRoutes,然後給每個ReRoute設置一個Key屬性。最後我們再Aggregates節點中的ReRouteKeys屬性中加入我們剛剛指定的兩個Key從而組成了兩個ReRoutes的聚合。當然我們還需要設置UpstreamPathTemplate匹配上游的用戶請求,它的工作方式與正常的ReRoute類似。

註意:不要把Aggregates中UpstreamPathTemplate設置的跟ReRoutes中的UpstreamPathTemplate設置成一樣。

下麵我們先上個實例例子先!演示代碼已經同步更新Github上。有興趣的朋友可以查看源碼:https://github.com/yilezhu/OcelotDemo

在開始實例前先把我們的ocelot Nuget包升級到最新的12.0.0版本,當然你也可以不進行升級。這裡需要註意一下,如果你升級到12.0.0的版本的話,那麼你config.AddOcelot()的用法會發生改變,需要傳入參數config.AddOcelot(hostingContext.HostingEnvironment)

1.為了演示的需要這裡我們新增一個類庫項目,分別新建兩個類,一個是商品Good類,一個是訂單Order類(這裡只是為了演示的需要,所以代碼很簡陋)如下所示:

 public class Goods
    {
        public int Id { get; set; }
        public string Content { get; set; }
    }

public class Orders
    {
        public int Id { get; set; }
        public string Content { get; set; }
    }
  1. 接下來我們給OrderApi以及GoodApi分別新建一個控制器,並返回相應的實體。如下所示:

    //GoodApi項目中
        [Route("api/[controller]")]
        [ApiController]
        public class GoodController : ControllerBase
        {
            // GET api/Good/5
            [HttpGet("{id}")]
            public ActionResult<string> Get(int id)
            {
                var item = new Goods
                {
                    Id = id,
                    Content = $"{id}的關聯的商品明細",
                };
                return JsonConvert.SerializeObject(item);
            }
        }
      //OrderApi項目中  
    [Route("api/[controller]")]
        [ApiController]
        public class OrderController : ControllerBase
        {
            // GET api/Order/5
            [HttpGet("{id}")]
            public ActionResult<string> Get(int id)
            {
                var item = new Orders {
                    Id=id,
                    Content=$"{id}的訂單明細",
                };
                return JsonConvert.SerializeObject(item);
            }
        }
  2. 接下來我們分別在ocelot.good.json以及ocelot.order.json中新增一個路由,並給出Keys.如下所示:

    這裡註意,跟上篇文章中的路由不同的是,這裡多了一個Key屬性。

    //ocelot.good.json
    {
          "DownstreamPathTemplate": "/api/Good/{id}",
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [
            {
              "Host": "localhost",
              "Port": 1001
            }
          ],
          "UpstreamPathTemplate": "/good/{id}",
          "UpstreamHttpMethod": [ "Get", "Post" ],
          "Key": "Good",
          "Priority": 2
        }
    //ocelot.order.json
    {
          "DownstreamPathTemplate": "/api/Order/{id}",
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [
            {
              "Host": "localhost",
              "Port": 1002
            }
          ],
          "UpstreamPathTemplate": "/order/{id}",
          "UpstreamHttpMethod": [ "Get", "Post" ],
          "Key": "Order",
          "Priority": 2
        }
  3. 在ocelot.all.json中加入聚合配置,如下所示:

      "Aggregates": [
        {
          "ReRouteKeys": [
            "Good",
            "Order"
          ],
          "UpstreamPathTemplate": "/GetOrderDetail/{id}"
        }
      ]

    註意:這裡AggregatesReRoutes同級,ReRouteKeys中填寫的數組就是上面步驟3中設置的Key屬性對應的值。

  4. 我們分別運行起來三個項目,然後訪問介面地址:http://localhost:1000/GetOrderDetail/1 會得到如下的聚合響應內容:

    1537715634581
    格式化後代碼如下:

    {
        "Good":{
            "Id":1,
            "Content":"1的關聯的商品明細"
        },
        "Order":{
            "Id":1,
            "Content":"1的訂單明細"
        }
    }
  5. 眼尖的朋友可能已經猜到了。聚合路由返回的內容就是json串。json串由ReRouteKeys組成,每個Key的內容就是具體下游響應的內容了!實例代碼已經同步更新到Github上,地址:https://github.com/yilezhu/OcelotDemo

    Ocelot將始終使用聚合請求返回內容類型application/json。還有需要註意的是聚合請求不會返回404請求。如果兩個下游都返回404狀態碼的話,這裡聚合後的響應也不會返回404,只會返回空的json串,拿上面的實例,如果兩個下游都返回404的話,那麼他的響應代碼類似下麵這樣:

    {
       "Good": ,
       "Order":
    }

    如果下游服務返回404,則聚合將僅為該下游服務返回任何內容。即使所有下游都返回404,它也不會將聚合響應更改為404。

服務發現

Ocelot允許您指定服務發現提供程式,並將使用它來查找Ocelot將請求轉發到的下游服務的主機和埠。目前,這僅在GlobalConfiguration部分中受支持,這意味著相同的服務發現提供程式將用於為ReRoute級別指定ServiceName的所有ReRoutes。

Consul

在使用Consul前你首先要做的就是安裝在Ocelot中提供Consul支持的NuGet包
Install-Package Ocelot.Provider.Consul
然後將下麵的內容添加在ConfigureServices方法中

services.AddOcelot()//註入Ocelot服務
                    .AddConsul(); 

GlobalConfiguration中需要加入以下內容。如果您未指定主機和埠,則將使用Consul預設值。

"ServiceDiscoveryProvider": {
    "Host": "localhost",
    "Port": 8500,
    "Type": "Consul"
}

註意:如果你採用AddOcelot()這種方式來自動載入ocelot配置文件的方式,那麼你需要新建一個ocelot.global.json文件,然後加入上面的配置:如下所示:

{
"GlobalConfiguration": {
  "ServiceDiscoveryProvider": {
    "Host": "localhost",
    "Port": 8500,
    "Type": "Consul"
  }
}
}
然後重新運行dotnet run命令會自動合併配置信息到Ocelot.json中,生成的對應內容如下:
​```C#
"ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul",
      "Token": null,
      "ConfigurationKey": null,
      "PollingInterval": 0
    }

這個上篇文章中已經進行了相關的介紹。

為了告訴Ocelot ReRoute是為其主機和埠使用服務發現提供程式,您必須在下游請求時添加要使用的ServiceName和負載均衡器。目前,Ocelot可以使用RoundRobin和LeastConnection演算法。如果未指定負載均衡器,則Ocelot將不會對請求進行負載均衡。

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "UpstreamPathTemplate": "/posts/{postId}",
    "UpstreamHttpMethod": [ "Put" ],
    "ServiceName": "product",
    "LoadBalancerOptions": {
        "Type": "LeastConnection"
    },
}

設置此項後,Ocelot將從服務發現提供程式中查找下游主機和埠,並跨任何可用服務進行負載平衡請求。

動態路由

作者的想法是在使用服務發現提供程式時啟用動態路由。在此模式下,Ocelot將使用上游路徑的第一個段來與服務發現提供程式一起查找下游服務。

例如,使用https://api.yilezhu.cn/product/products 等網址調用ocelot 。Ocelot將採用產品路徑的第一部分product,並將其用作在Consul中查找服務的Key。如果consul返回一個服務,Ocelot將使用從consul返回的主機和埠以及剩餘路徑段組合後的Url來進行請求的響應。,如:http:// hostfromconsul:portfromconsul/products。Ocelot將正常向下游URL轉發查詢字元串。即query

要啟用動態路由,您需要在配置中保留0個ReRoutes。目前您無法混合動態和配置ReRoutes。除此之外,您還需要指定上面概述的Service Discovery提供程式詳細信息和下游http / https方案作為DownstreamScheme。

除此之外,您還可以設置RateLimitOptions,QoSOptions,LoadBalancerOptions和HttpHandlerOptions,DownstreamScheme(您可能希望在https上調用Ocelot,但可以通過http與私有服務進行通信),這些將應用於所有動態ReRoutes。

配置可能看起來像:

{
    "ReRoutes": [],
    "Aggregates": [],
    "GlobalConfiguration": {
        "RequestIdKey": null,
        "ServiceDiscoveryProvider": {
            "Host": "localhost",
            "Port": 8500,
            "Type": "Consul",
            "Token": null,
            "ConfigurationKey": null
        },
        "RateLimitOptions": {
            "ClientIdHeader": "ClientId",
            "QuotaExceededMessage": null,
            "RateLimitCounterPrefix": "ocelot",
            "DisableRateLimitHeaders": false,
            "HttpStatusCode": 429
        },
        "QoSOptions": {
            "ExceptionsAllowedBeforeBreaking": 0,
            "DurationOfBreak": 0,
            "TimeoutValue": 0
        },
        "BaseUrl": null,
            "LoadBalancerOptions": {
            "Type": "LeastConnection",
            "Key": null,
            "Expiry": 0
        },
        "DownstreamScheme": "http",
        "HttpHandlerOptions": {
            "AllowAutoRedirect": false,
            "UseCookieContainer": false,
            "UseTracing": false
        }
    }
}

Ocelot還允許您設置DynamicReRoutes,允許您為每個下游服務設置速率限制規則。如果您有一個產品和搜索服務,並且您希望對另一個進行速率限制,則此功能非常有用。這方面的一個例子如下。

{
    "DynamicReRoutes": [
        {
        "ServiceName": "product",
        "RateLimitRule": {
                "ClientWhitelist": [],
                "EnableRateLimiting": true,
                "Period": "1s",
                "PeriodTimespan": 1000.0,
                "Limit": 3
            }
        }
    ],
    "GlobalConfiguration": {
        "RequestIdKey": null,
        "ServiceDiscoveryProvider": {
            "Host": "localhost",
            "Port": 8523,
            "Type": "Consul"
        },
        "RateLimitOptions": {
            "ClientIdHeader": "ClientId",
            "QuotaExceededMessage": "",
            "RateLimitCounterPrefix": "",
            "DisableRateLimitHeaders": false,
            "HttpStatusCode": 428
        }
        "DownstreamScheme": "http",
    }
}

此配置意味著如果您在/product/上進入Ocelot請求,則動態路由將啟動,並且ocelot將使用針對DynamicReRoutes部分中的產品服務的速率限制設置。

GitHub地址

https://github.com/yilezhu/OcelotDemo

Ocelot簡易教程目錄

  1. Ocelot簡易教程(一)之Ocelot是什麼
  2. Ocelot簡易教程(二)之快速開始1
  3. Ocelot簡易教程(二)之快速開始2
  4. Ocelot簡易教程(三)之主要特性及路由詳解
  5. Ocelot簡易教程(四)之請求聚合以及服務發現

    總結

    本文接著上篇文章進行了Ocelot請求聚合功能以及服務發現功能的介紹,並且對Ocelot動態路由功能也進行了簡單的闡述。對於請求聚合這塊進行了相關實例代碼的演示,並已經更新到Github上面了!希望能對大家有所幫助!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在我們的應用程式中日誌是不可缺少的部分,在Apache中由一個功能無比強大的日誌組件,它提供了方便的日誌記錄,這個開源的項目就是我們慣用的Log4j,jar包我麽們一顆取Apache官網下載最新版本的。log4j下載地址 一.入門篇 1.打開我們的Eclipse新建一個Java項目並且導入Log4j ...
  • 在開源文件大行其道的今天,基於java種種解決方案和框架紛繪踏至而來,猶如浩瀚如海,看不完也學不盡。在採用這些解決方案和框架進行項目開發時,往往會出現當程式卡殼時,既無異常提示信息亦沒有與之對應的日誌輸出的局面。每每出現這樣的困境時,往往只能通過打斷點來一步一步調試跟蹤來解決。更有甚者,基於某一底層... ...
  • 題目介紹:現在輸入一組數據,寫入學生的考試分數。已知學生數為N,學生編號為1到N,且0<N<=30000,每個學生都有一個分數;操作數為M且0<M<5000。輸入第一行為N M,接下來是1行N列數據代表學生的初試分數,接下來是M行操作數據。已知操作有兩種,分為Q和U。一次操作的格式為 C A B,當 ...
  • 線性表是一種隨機存取的結構,和鏈表不同,鏈表順序存取的結構。但是,線性表是一種順序存儲的結構,而鏈表是鏈式存儲結構。兩者都是線性的,但區別不同。 進入主題: 1.假如有一串數據元素,要求刪除其中的重覆元素。 首先想到的是用兩層迴圈,第一層從第一個元素開始,第二層從第一層元素的下一個元素開始。 就是假 ...
  • 1、指令:<%@ 指令名 屬性名="值"%> 1) page:page指令告訴servlet容器,這是一個Jsp頁面 pageEncoding 指頁面文本的字元集編碼 contentType 告訴Browser 和Servlet端,要使用哪個格式哪個字元集進行解析 獨立的@page指令,可以使用im ...
  • 在分散式系統中,服務發生異常是很正常的現象。為了處理這類“例外”,可以採取不同的應對策略,斷路器模式即是其中一種方法。這個模式的主要特點是其可以阻斷失敗的級聯影響,不會因為一個服務的失敗導致其它關聯服務一併失敗。 在Spring Cloud生態系統中有Hystrix類庫可以提供這個模式的解決方案,而 ...
  • 調用windows的imm32.dll完成窗體接收輸入法功能. 代碼如下 public ImeComponent(Form from) { var handle = from.Handle; hIMC = ImmGetContext(handle); this.handle = handle; } ...
  • 程式源代碼Gitee項目地址:https://gitee.com/xiao_ge_ge/WordCount.git 一:介紹: 這次作業的主要任務: WordCount的需求可以概括為:對程式設計語言源文件統計字元數、單詞數、行數,統計結果以指定格式輸出到預設文件中,以及其他擴展功能,並能夠快速地處 ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...