日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Ocelot(五)- 流量限制、服务质量

發(fā)布時(shí)間:2023/12/4 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Ocelot(五)- 流量限制、服务质量 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作者:markjiang7m2
原文地址:https://www.cnblogs.com/markjiang7m2/p/10965300.html
源碼地址:https://gitee.com/Sevenm2/OcelotDemo

本文是我關(guān)于Ocelot系列文章的第五篇,流量限制、服務(wù)質(zhì)量。Ocelot允許針對(duì)具體的服務(wù)接口進(jìn)行流量限制,以便下游服務(wù)不會(huì)過(guò)載而影響響應(yīng)速度。服務(wù)質(zhì)量則是Ocelot根據(jù)下游服務(wù)響應(yīng)的結(jié)果做出判斷,當(dāng)超過(guò)一定次數(shù)的響應(yīng)失敗時(shí),Ocelot認(rèn)為該服務(wù)不可用,自動(dòng)產(chǎn)生熔斷,在一定的時(shí)間范圍內(nèi)不再向該服務(wù)轉(zhuǎn)發(fā)請(qǐng)求,同時(shí)Ocelot也支持自定義的請(qǐng)求超時(shí)時(shí)間,當(dāng)下游響應(yīng)超過(guò)設(shè)定的時(shí)間,會(huì)認(rèn)為該服務(wù)響應(yīng)失敗。

關(guān)于更多的Ocelot功能介紹,可以查看我的系列文章

  • Ocelot - .Net Core開(kāi)源網(wǎng)關(guān)

  • Ocelot(二)- 請(qǐng)求聚合與負(fù)載均衡

  • Ocelot(三)- 服務(wù)發(fā)現(xiàn)

  • Ocelot(四)- 認(rèn)證與授權(quán)

本文中涉及案例的完整代碼都可以從我的代碼倉(cāng)庫(kù)進(jìn)行下載。

  • 倉(cāng)庫(kù)地址:https://gitee.com/Sevenm2/OcelotDemo

案例六 流量限制

Ocelot支持流量限制,只要在路由中添加 RateLimitOptions配置即可

"RateLimitOptions": { "ClientWhiteList": [ "markadmin" ], "EnableRateLimiting": true, "Period": "1m", "PeriodTimespan": 30, "Limit": 5 }


  • ClientWhiteList:數(shù)組,在請(qǐng)求頭中包含ClientId=xxx的請(qǐng)求不受限流控制,其中ClientId這個(gè)key可以修改,xxx表示配置的白名單。

  • EnableRateLimiting:是否啟用限流

  • Period:限流控制的時(shí)間周期,輸入單位支持s(秒), m(分), h(時(shí)), d(天)

  • PeriodTimespan:恢復(fù)等待時(shí)間,當(dāng)訪問(wèn)超過(guò)限流限制的次數(shù)后,需要等待的時(shí)間,單位為s,如當(dāng)一分鐘內(nèi)訪問(wèn)超過(guò)5次,就需要等待30秒后,訪問(wèn)才會(huì)重新有效

  • Limit:一個(gè)時(shí)間周期內(nèi)允許訪問(wèn)的最大次數(shù)。

下面來(lái)看案例,在 ReRoutes中添加一組路由

  • {

  • "DownstreamPathTemplate": "/api/ocelot/{postId}",

  • "DownstreamScheme": "http",

  • "DownstreamHostAndPorts": [

  • {

  • "Host": "localhost",

  • "Port": 8001

  • }

  • ],

  • "UpstreamPathTemplate": "/ocelot/ratelimit/{postId}",

  • "UpstreamHttpMethod": [ "Get" ],

  • "Priority": 2,

  • "RateLimitOptions": {

  • "ClientWhiteList": [

  • "markadmin"

  • ],

  • "EnableRateLimiting": true,

  • "Period": "1m",

  • "PeriodTimespan": 30,

  • "Limit": 5

  • }

  • }

  • 在這里我只是添加多了一組路由,但下游服務(wù)接口是重用了之前使用過(guò)的接口,流量限制部分配置上面已經(jīng)介紹過(guò)了。下面運(yùn)行來(lái)看結(jié)果。

    當(dāng)我第一次訪問(wèn) http://localhost:4727/ocelot/ratelimit/5的時(shí)候,得到了正常的返回結(jié)果

    而且,在請(qǐng)求頭可以看到流量限制的相關(guān)信息

    然后,我又很快地繼續(xù)發(fā)出請(qǐng)求,可以看到,當(dāng)我第六次發(fā)出請(qǐng)求的時(shí)候,得到了 429ToManyRequests的狀態(tài)

    而此時(shí)的請(qǐng)求頭信息也會(huì)不一樣,這里可以看到 Retry-After28,意思是在28秒后可以恢復(fù)請(qǐng)求

    這證明,我們的Ocelot網(wǎng)關(guān)流量限制的作用起效了,而且與我們的配置一致。
    在等待30秒之后,我重新發(fā)出請(qǐng)求,又得到了正常的返回結(jié)果

    當(dāng)我在請(qǐng)求頭中加上 [ClientId]=markadmin后,清空Postman的請(qǐng)求記錄,重新開(kāi)始發(fā)出請(qǐng)求,無(wú)論請(qǐng)求多少次,Ocelot也不會(huì)對(duì)我的訪問(wèn)進(jìn)行限流

    這里對(duì)于PeriodTimespan(恢復(fù)等待時(shí)間)的算法,我倒是有點(diǎn)疑問(wèn)的。我一開(kāi)始的理解是,基于上面案例的配置,當(dāng)一分鐘內(nèi)訪問(wèn)超過(guò)5次時(shí),就需要等待 Period + PeriodTimespan,也就是從第一個(gè)有效請(qǐng)求開(kāi)始算起,一分半鐘之后Ocelot才會(huì)重新正常轉(zhuǎn)發(fā)請(qǐng)求,但是我做了幾次重復(fù)實(shí)驗(yàn),得到的結(jié)果都是:當(dāng)一分鐘內(nèi)訪問(wèn)到第1次時(shí),Ocelot開(kāi)始進(jìn)入 PeriodTimespan時(shí)間內(nèi)的倒計(jì)時(shí),也就是實(shí)際的重置時(shí)間為 PeriodTimespan

    為了更加明確地驗(yàn)證這個(gè)問(wèn)題,我使用 OcelotConsole項(xiàng)目進(jìn)行測(cè)試。
    首先,修改路由配置如下:

  • {

  • "DownstreamPathTemplate": "/api/ocelot/{postId}",

  • "DownstreamScheme": "http",

  • "DownstreamHostAndPorts": [

  • {

  • "Host": "localhost",

  • "Port": 8001

  • }

  • ],

  • "UpstreamPathTemplate": "/ocelot/ratelimit/{postId}",

  • "UpstreamHttpMethod": [ "Get" ],

  • "Priority": 2,

  • "RateLimitOptions": {

  • "ClientWhiteList": [

  • "markadmin"

  • ],

  • "EnableRateLimiting": true,

  • "Period": "1m",

  • "PeriodTimespan": 10,

  • "Limit": 5

  • }

  • }

  • 然后,在 OcelotConsole項(xiàng)目中添加代碼如下:

  • public static async Task Main(string[] args)

  • {

  • using (var client = new HttpClient())

  • {

  • for (var i = 0; i < 100; i++)

  • {

  • Console.WriteLine(DateTime.Now);


  • var result = await client.GetAsync("http://localhost:4727/ocelot/ratelimit/5");

  • Console.WriteLine($"{result.StatusCode}, {result.Content.ReadAsStringAsync().Result}");

  • System.Threading.Thread.Sleep(1000);

  • }

  • Console.Read();

  • }

  • }

  • 每隔1s就發(fā)出一次請(qǐng)求,運(yùn)行,在命令窗口得到以下輸出:

  • 2019/6/3 13:33:31

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:32

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:33

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:34

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:35

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:36

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:37

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:38

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:39

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:40

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:41

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:43

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:44

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:45

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:46

  • OK, This is from localhost:8001, path: /api/ocelot/5

  • 2019/6/3 13:33:47

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:48

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:49

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:50

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 2019/6/3 13:33:51

  • TooManyRequests, API calls quota exceeded! maximum admitted 5 per 1m.

  • 然后,我又通過(guò)修改參數(shù),得出如下結(jié)果:

    • PeriodTimespan=10, Limit=5:5個(gè)成功,5個(gè)失敗

    • PeriodTimespan=10, Limit=6:6個(gè)成功,4個(gè)失敗

    • PeriodTimespan=20, Limit=5:5個(gè)成功,15個(gè)失敗

    • PeriodTimespan=30, Limit=5:5個(gè)成功,25個(gè)失敗

    似乎都是與我前面得到的結(jié)論相同,與官方文檔不一致。
    我在GitHub上提了一個(gè)issue:https://github.com/ThreeMammals/Ocelot/issues/910,期待能得到答復(fù)。

    流量限制的全局配置

  • "RateLimitOptions": {

  • "DisableRateLimitHeaders": true,

  • "QuotaExceededMessage": "Customize Tips!",

  • "HttpStatusCode": 999,

  • "ClientIdHeader": "Test"

  • }

    • DisableRateLimitHeaders:當(dāng)設(shè)為true時(shí),請(qǐng)求頭中就不會(huì)輸出流量限制的相關(guān)信息,默認(rèn)值:"false"

    • QuotaExceededMessage:當(dāng)請(qǐng)求數(shù)量超出流量限制時(shí),輸出的信息,默認(rèn)值:"API calls quota exceeded! maximum admitted?{Limit}?per?{Period}."

    • HttpStatusCode:當(dāng)請(qǐng)求數(shù)量超出流量限制時(shí),輸出的狀態(tài)碼,默認(rèn)值:"429"

    • ClientIdHeader:標(biāo)識(shí)為白名單中的客戶端的請(qǐng)求頭key,默認(rèn)值:"ClientId"


    案例七 服務(wù)質(zhì)量

    Ocelot支持服務(wù)質(zhì)量與熔斷,意味著當(dāng)下游服務(wù)不可用時(shí),Ocelot會(huì)進(jìn)行自動(dòng)熔斷,不再將請(qǐng)求轉(zhuǎn)發(fā)給該下游服務(wù)。來(lái)看看配置

  • "QoSOptions": {

  • "ExceptionsAllowedBeforeBreaking":3,

  • "DurationOfBreak":3000,

  • "TimeoutValue":5000

  • }

    • ExceptionsAllowedBeforeBreaking:允許異常次數(shù),當(dāng)Ocelot轉(zhuǎn)發(fā)給該下游服務(wù)連續(xù)出現(xiàn)異常次數(shù)達(dá)到該數(shù)字時(shí),Ocelot會(huì)進(jìn)行自動(dòng)熔斷,一段時(shí)間內(nèi)不再向該下游服務(wù)轉(zhuǎn)發(fā)請(qǐng)求

    • DurationOfBreak:熔斷時(shí)間,單位為ms(毫秒),持續(xù)多長(zhǎng)時(shí)間不向該下游服務(wù)轉(zhuǎn)發(fā)請(qǐng)求

    • TimeoutValue:服務(wù)質(zhì)量配置項(xiàng),超時(shí)時(shí)間,單位為ms(毫秒),當(dāng)Ocelot向下游服務(wù)轉(zhuǎn)發(fā)請(qǐng)求多長(zhǎng)時(shí)間后,自動(dòng)認(rèn)為該請(qǐng)求超時(shí)

    ExceptionsAllowedBeforeBreaking 必須跟 DurationOfBreak一起使用,TimeoutValue可以單獨(dú)使用。

    首先需要安裝 Polly支持程序,通過(guò)Nuget搜索 Ocelot.Provider.Polly或者通過(guò)以下命令安裝

  • Install-Package Ocelot.Provider.Polly

  • 然后在Startup.cs中的 ConfigureServices方法注冊(cè)該中間件

  • using Ocelot.Provider.Polly;

  • public void ConfigureServices(IServiceCollection services)

  • {

  • ……

  • services.AddOcelot()

  • .AddPolly();

  • ……

  • }

  • ReRoutes中添加一組路由

  • {

  • "DownstreamPathTemplate": "/api/ocelot/{postId}",

  • "DownstreamScheme": "http",

  • "DownstreamHostAndPorts": [

  • {

  • "Host": "localhost",

  • "Port": 8001

  • }

  • ],

  • "UpstreamPathTemplate": "/ocelot/qos/{postId}",

  • "UpstreamHttpMethod": [ "Get" ],

  • "Priority": 2,

  • "QoSOptions": {

  • "ExceptionsAllowedBeforeBreaking": 3,

  • "DurationOfBreak": 3000,

  • "TimeoutValue": 5000

  • }

  • }

  • 為了看出熔斷效果,我將 8001端口的下游服務(wù)停止了,然后運(yùn)行OcelotDemo項(xiàng)目

    當(dāng)?shù)谝淮蜗蚓W(wǎng)關(guān)發(fā)出請(qǐng)求時(shí),得到 500的狀態(tài)碼

    連續(xù)3次請(qǐng)求過(guò)后,就會(huì)得到 503的狀態(tài)碼,證明Ocelot已經(jīng)產(chǎn)生熔斷

    總結(jié)

    在這篇文章中就跟大家介紹了Ocelot的兩個(gè)基礎(chǔ)功能,在路由中進(jìn)行配置即可使用,不需要依賴于第三方的服務(wù)。當(dāng)然在我實(shí)踐的過(guò)程中產(chǎn)生的一個(gè)疑問(wèn)暫時(shí)還沒(méi)得到答案,如果有知道原因的朋友也可以給我留言,感激不盡。
    結(jié)合前面的幾篇文章,大家在設(shè)計(jì)項(xiàng)目API網(wǎng)關(guān)的時(shí)候就可以綜合地考慮到底哪些功能應(yīng)該配置使用,如何適當(dāng)?shù)亟⒙酚杀怼A硗?#xff0c;我在這幾個(gè)案例中為了突出要介紹的功能,基本上都是一組路由單獨(dú)配置一個(gè)功能,而在實(shí)際項(xiàng)目中通常都是需要在一組路由當(dāng)中同時(shí)配置多個(gè)功能的,希望大家在實(shí)際項(xiàng)目中能夠靈活運(yùn)用。今天就先跟大家介紹到這里,希望大家能持續(xù)關(guān)注我們。


    總結(jié)

    以上是生活随笔為你收集整理的Ocelot(五)- 流量限制、服务质量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。