Ocelot(五)- 流量限制、服务质量
作者:markjiang7m2
原文地址:https://www.cnblogs.com/markjiang7m2/p/10965300.html
源碼地址:https://gitee.com/Sevenm2/OcelotDemo
本文是我關于Ocelot系列文章的第五篇,流量限制、服務質量。Ocelot允許針對具體的服務接口進行流量限制,以便下游服務不會過載而影響響應速度。服務質量則是Ocelot根據下游服務響應的結果做出判斷,當超過一定次數的響應失敗時,Ocelot認為該服務不可用,自動產生熔斷,在一定的時間范圍內不再向該服務轉發請求,同時Ocelot也支持自定義的請求超時時間,當下游響應超過設定的時間,會認為該服務響應失敗。
關于更多的Ocelot功能介紹,可以查看我的系列文章
Ocelot - .Net Core開源網關
Ocelot(二)- 請求聚合與負載均衡
Ocelot(三)- 服務發現
Ocelot(四)- 認證與授權
本文中涉及案例的完整代碼都可以從我的代碼倉庫進行下載。
倉庫地址:https://gitee.com/Sevenm2/OcelotDemo
案例六 流量限制
Ocelot支持流量限制,只要在路由中添加 RateLimitOptions配置即可
"RateLimitOptions": { "ClientWhiteList": [ "markadmin" ], "EnableRateLimiting": true, "Period": "1m", "PeriodTimespan": 30, "Limit": 5 }ClientWhiteList:數組,在請求頭中包含ClientId=xxx的請求不受限流控制,其中ClientId這個key可以修改,xxx表示配置的白名單。
EnableRateLimiting:是否啟用限流
Period:限流控制的時間周期,輸入單位支持s(秒), m(分), h(時), d(天)
PeriodTimespan:恢復等待時間,當訪問超過限流限制的次數后,需要等待的時間,單位為s,如當一分鐘內訪問超過5次,就需要等待30秒后,訪問才會重新有效
Limit:一個時間周期內允許訪問的最大次數。
下面來看案例,在 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
}
}
在這里我只是添加多了一組路由,但下游服務接口是重用了之前使用過的接口,流量限制部分配置上面已經介紹過了。下面運行來看結果。
當我第一次訪問 http://localhost:4727/ocelot/ratelimit/5的時候,得到了正常的返回結果
而且,在請求頭可以看到流量限制的相關信息
然后,我又很快地繼續發出請求,可以看到,當我第六次發出請求的時候,得到了 429ToManyRequests的狀態
而此時的請求頭信息也會不一樣,這里可以看到 Retry-After→28,意思是在28秒后可以恢復請求
這證明,我們的Ocelot網關流量限制的作用起效了,而且與我們的配置一致。
在等待30秒之后,我重新發出請求,又得到了正常的返回結果
當我在請求頭中加上 [ClientId]=markadmin后,清空Postman的請求記錄,重新開始發出請求,無論請求多少次,Ocelot也不會對我的訪問進行限流
這里對于PeriodTimespan(恢復等待時間)的算法,我倒是有點疑問的。我一開始的理解是,基于上面案例的配置,當一分鐘內訪問超過5次時,就需要等待 Period + PeriodTimespan,也就是從第一個有效請求開始算起,一分半鐘之后Ocelot才會重新正常轉發請求,但是我做了幾次重復實驗,得到的結果都是:當一分鐘內訪問到第1次時,Ocelot開始進入 PeriodTimespan時間內的倒計時,也就是實際的重置時間為 PeriodTimespan。
為了更加明確地驗證這個問題,我使用 OcelotConsole項目進行測試。
首先,修改路由配置如下:
{
"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項目中添加代碼如下:
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就發出一次請求,運行,在命令窗口得到以下輸出:
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.
然后,我又通過修改參數,得出如下結果:
PeriodTimespan=10, Limit=5:5個成功,5個失敗
PeriodTimespan=10, Limit=6:6個成功,4個失敗
PeriodTimespan=20, Limit=5:5個成功,15個失敗
PeriodTimespan=30, Limit=5:5個成功,25個失敗
似乎都是與我前面得到的結論相同,與官方文檔不一致。
我在GitHub上提了一個issue:https://github.com/ThreeMammals/Ocelot/issues/910,期待能得到答復。
流量限制的全局配置
"RateLimitOptions": {
"DisableRateLimitHeaders": true,
"QuotaExceededMessage": "Customize Tips!",
"HttpStatusCode": 999,
"ClientIdHeader": "Test"
}
DisableRateLimitHeaders:當設為true時,請求頭中就不會輸出流量限制的相關信息,默認值:"false"
QuotaExceededMessage:當請求數量超出流量限制時,輸出的信息,默認值:"API calls quota exceeded! maximum admitted?{Limit}?per?{Period}."
HttpStatusCode:當請求數量超出流量限制時,輸出的狀態碼,默認值:"429"
ClientIdHeader:標識為白名單中的客戶端的請求頭key,默認值:"ClientId"
案例七 服務質量
Ocelot支持服務質量與熔斷,意味著當下游服務不可用時,Ocelot會進行自動熔斷,不再將請求轉發給該下游服務。來看看配置
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking":3,
"DurationOfBreak":3000,
"TimeoutValue":5000
}
ExceptionsAllowedBeforeBreaking:允許異常次數,當Ocelot轉發給該下游服務連續出現異常次數達到該數字時,Ocelot會進行自動熔斷,一段時間內不再向該下游服務轉發請求
DurationOfBreak:熔斷時間,單位為ms(毫秒),持續多長時間不向該下游服務轉發請求
TimeoutValue:服務質量配置項,超時時間,單位為ms(毫秒),當Ocelot向下游服務轉發請求多長時間后,自動認為該請求超時
ExceptionsAllowedBeforeBreaking 必須跟 DurationOfBreak一起使用,TimeoutValue可以單獨使用。
首先需要安裝 Polly支持程序,通過Nuget搜索 Ocelot.Provider.Polly或者通過以下命令安裝
Install-Package Ocelot.Provider.Polly
然后在Startup.cs中的 ConfigureServices方法注冊該中間件
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端口的下游服務停止了,然后運行OcelotDemo項目
當第一次向網關發出請求時,得到 500的狀態碼
連續3次請求過后,就會得到 503的狀態碼,證明Ocelot已經產生熔斷
總結
在這篇文章中就跟大家介紹了Ocelot的兩個基礎功能,在路由中進行配置即可使用,不需要依賴于第三方的服務。當然在我實踐的過程中產生的一個疑問暫時還沒得到答案,如果有知道原因的朋友也可以給我留言,感激不盡。
結合前面的幾篇文章,大家在設計項目API網關的時候就可以綜合地考慮到底哪些功能應該配置使用,如何適當地建立路由表。另外,我在這幾個案例中為了突出要介紹的功能,基本上都是一組路由單獨配置一個功能,而在實際項目中通常都是需要在一組路由當中同時配置多個功能的,希望大家在實際項目中能夠靈活運用。今天就先跟大家介紹到這里,希望大家能持續關注我們。
總結
以上是生活随笔為你收集整理的Ocelot(五)- 流量限制、服务质量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Docker最全教程之MySQL容器化
- 下一篇: Ocelot(三)- 服务发现