【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流
上篇文章我介紹了如何在網關上增加自定義客戶端授權功能,從設計到編碼實現,一步一步詳細講解,相信大家也掌握了自定義中間件的開發技巧了,本篇我們將介紹如何實現自定義客戶端的限流功能,來進一步完善網關的基礎功能。
.netcore項目實戰交流群(637326624),有興趣的朋友可以在群里交流討論。
一、功能描述
限流就是為了保證網關在高并發或瞬時并發時,在服務能承受范圍內,犧牲部分請求為代價,保證系統的整體可用性而做的安全策略,避免單個服務影響整體網關的服務能力。
比如網關有商品查詢接口 ,能接受的極限請求是每秒100次查詢,如果此時不限流,可能因為瞬時請求太大,造成服務卡死或崩潰的情況,這種情況可以使用Ocelot客戶端全局限流即可滿足需求,現在又有一個需求,我需要把接口開放給A公司,他們也要查詢這個商品接口,這時A公司請求頻率也是我們設置的每秒100次請求,顯然我們不希望A公司有這么高的請求頻率,我只會給A公司最大每秒一次的請求,那怎么實現呢?這時我們就無法通過Ocelot配置限流來進行自定義控制了,這塊就需要我們增加自定義限流管道來實現功能。
下面我們就該功能如何實現展開講解,希望大家先理解下功能需求,然后在延伸到具體實現。
二、數據庫設計
限流這塊設計表結構和關系如下。
主要有限流規則表、路由限流規則表、限流組表、限流組策略表、客戶端授權限流組表、客戶端白名單表組成,設計思想就是客戶端請求時先檢查是否在白名單,如果白名單不存在,就檢查是否在限流組里,如果在限流組里校驗限流的規則是什么,然后比對這個規則和當前請求次數看是否能夠繼續訪問,如果超過限流策略直接返回429狀態,否則路由到下端請求。
梳理下后發現流程不是很復雜,最起碼實現的思路非常清晰,然后我們就運用上篇自定義授權中間件的方式來開發我們第二個中間件,自定義限流中間件。
三、功能實現
1、功能開啟配置
網關應該支持自定義客戶端限流中間件是否啟用,因為一些小型項目是不需要對每個客戶端進行單獨限流的,中型和大型項目才有可能遇到自定義配置情況,所以我們需要在配置文件增加配置選項。在AhphOcelotConfiguration.cs配置類中增加屬性,默認不開啟。
那我們如何把自定義的限流增加到網關流程里呢?這塊我們就需要訂制自己的限流中間件。
2、實現客戶端限流中間件
首先我們定義一個自定義限流中間件AhphClientRateLimitMiddleware,需要繼承OcelotMiddleware,然后我們要實現Invoke方法,詳細代碼如下。
首先我們來分析下我們的代碼,為了知道是哪個客戶端請求了我們網關,需要提取clientId,分別從無需授權接口和需要授權接口兩個方式提取,如果提取不到值直接給定默認值,放到全局限流里,防止繞過限流策略。然后根據客戶端通過4步檢驗下是否允許訪問(后面會介紹這4步怎么實現),如果滿足限流策略直接返回限流錯誤提醒。
有了這個中間件,那么如何添加到Ocelot的管道里呢?上一篇介紹的非常詳細,這篇我就不介紹了,自定義限流中間件擴展AhphClientRateLimitMiddlewareExtensions,代碼如下。
有了這個中間件擴展后,我們就在管道的合適地方加入我們自定義的中間件。我們添加我們自定義的管道擴展OcelotPipelineExtensions,然后把自定義限流中間件加入到認證之后。
//添加自定義限流中間件 2018-11-18 金焰的世界builder.UseAhphClientRateLimitMiddleware();現在我們完成了網關的擴展和應用,是時候把定義的IClientRateLimitProcessor接口實現了 ,是不是感覺做一個中間件很簡單呢?而且每一步都是層層關聯,只要一步一步按照自己的想法往下寫就能實現。
3、結合數據庫實現校驗及緩存
首先我們新建AhphClientRateLimitProcessor類來實現接口,中間增加必要的緩存和業務邏輯,詳細代碼如下。
我們來分析下這塊代碼,里面涉及了限流的提取和實現規則,首先我們注入了數據庫實體接口和緩存信息,實現步驟是參照之前的流程。
主要流程如下:
1、路由是否啟用限流,如果未啟用直接完成校驗,如果進行第2步判斷.
2、客戶端對應的路由是否設置了限流規則,如果未設置,直接完成校驗,否則進入第3步判斷.
3、客戶端是否開啟了路由白名單功能,如果開啟了直接完成校驗,否則進入第4步。
4、使用Redis來進行限流的判斷。使用的就是計數器方法,結合redis設置key的過期時間來實現的。
為了減少后端請求,在數據庫提取的方法前都加入了緩存,現在我們需要把用到的接口添加到入口進行注入。
builder.Services.AddSingleton<IOcelotCache<RateLimitRuleModel>, InRedisCache<RateLimitRuleModel>>();builder.Services.AddSingleton<IOcelotCache<AhphClientRateLimitCounter?>, InRedisCache<AhphClientRateLimitCounter?>>();現在我們還剩下IClientRateLimitRepository接口未實現,現在只要實現這個接口,然后注入下,我們就完成了限流中間件的開發了,我們根據限流的流程,梳理了實現,現在有3個方法需要進行實現。
新建SqlServerClientRateLimitRepository類,來開始實現我們與數據庫的操作,有了上面的分析思路,現在就是把一個一個詳細確定的方法實現而已,太簡單了,只要花了幾分鐘后,就可以瞬間寫出如下代碼。
主要就是注意下表之間的關系,把實現注入到AddAhphOcelot里,現在就可以測試開始自定義客戶端限流中間件。
builder.Services.AddSingleton<IClientRateLimitRepository, SqlServerClientRateLimitRepository>();4、測試限流中間件
為了把把所有情況都測試一遍,先從開啟限流,什么都不寫入看是否能夠正常運行。
option.ClientRateLimit = true;還記得我們上篇的兩個客戶端和能訪問的頁面嗎?就用它們來測試,結果顯示正常,說明不開啟限流沒有影響。
開啟/cjy/values2個限流規則,一個每1分鐘訪問1次,一個每1分鐘訪問60次。
--1、插入限流規則INSERT INTO AhphLimitRule VALUES('每1分鐘訪問1次','1m',1,1);INSERT INTO AhphLimitRule VALUES('每1分鐘訪問60次','1m',60,1);--2、應用到/cjy/values路由INSERT INTO AhphReRouteLimitRule VALUES(1,1);INSERT INTO AhphReRouteLimitRule VALUES(2,1);因為還未給客戶端應用規則,所以應該也是可以正常訪問,可以使用PostMan測試下,測試時需要注意下緩存,因為所有的訪問都啟用的默認緩存策略,經測試得到預期效果。
現在開始把限流分別應用到客戶端1和客戶端2,看下限流效果。
然后使用PostMan測試客戶端1和客戶端2,結果如下,超過設置的頻率后不返回結果,達到預期目的,但是返回的是404錯誤,強迫癥患者表示這不優雅啊,應該是429 Too Many Requests,那我們如何修改呢?
這里就需要了解下錯誤信息是如何輸出的,需要查看Ocelot源碼,您會發現IErrorsToHttpStatusCodeMapper接口和ErrorsToHttpStatusCodeMapper實現,代碼如下,
可以發現因為未定義RateLimitOptionsError錯誤的狀態碼,增加一個判斷即可,那我們重寫下把,然后集成在我們自己的中間件里,這塊在后期有很多擴展能夠用到,增加如下代碼。
if (errors.Any(e => e.Code == OcelotErrorCode.RateLimitOptionsError)) { ? ?return 429; }然后重新注入下。
builder.Services.AddSingleton<IErrorsToHttpStatusCodeMapper, AhphErrorsToHttpStatusCodeMapper>();在重新測試下訪問限流地址。
奈斯,達到了我們預期的效果,.netcore?開發魅力體現出來了嗎?
我們增加客戶端1的路由白名單,然后再繼續測試看是否解除限流限制?
--6、設置客戶端1/cjy/values路由白名單INSERT INTO AhphClientReRouteWhiteList VALUES(1,2);注意測試時清除緩存
經測試不受限流控制,達到了我們最終目的,到此限流功能全部實現。
5、增加mysql支持
直接重寫IClientRateLimitRepository實現,然后注入實現。
builder.Services.AddSingleton<IClientRateLimitRepository, MySqlClientRateLimitRepository>();四、總結及預告
本篇我們講解的是網關如何實現自定義客戶端限流功能,從設計到實現一步一步詳細講解,雖然只用一篇就寫完了,但是涉及的知識點還是非常多的,希望大家認真理解實現的思想,看我是如何從規劃到實現的,為了更好的幫助大家理解。大家可以根據博客內容自己手動實現下,有利于消化,如果在操作中遇到什么問題,可以加.NET Core項目實戰交流群(QQ群號:637326624)咨詢作者。
從下一篇開始介紹IdentityServer4的相關應用,并配合我們的網關實現認證,在跟我教程學習的朋友,可以自己先預習下。
相關文章:
AspNetCore中使用Ocelot之 IdentityServer4
Ocelot-基于.NET Core的開源網關實現
.NET Core微服務之基于Ocelot+IdentityServer實現統一驗證與授權
Swagger如何訪問Ocelot中帶權限驗證的API
Ocelot.JwtAuthorize:一個基于網關的Jwt驗證包
.NET Core微服務之基于Ocelot實現API網關服務
.NET Core微服務之基于Ocelot實現API網關服務(續)
.NET微服務體系結構中為什么使用Ocelot實現API網關
Ocelot簡易教程(一)之Ocelot是什么
Ocelot簡易教程(二)之快速開始1
Ocelot簡易教程(二)之快速開始2
Ocelot簡易教程(三)之主要特性及路由詳解
Ocelot簡易教程(四)之請求聚合以及服務發現
Ocelot簡易教程(五)之集成IdentityServer認證以及授權
Ocelot簡易教程(六)之重寫配置文件存儲方式并優化響應數據
Ocelot簡易教程(七)之配置文件數據庫存儲插件源碼解析
ASP.NET Core中Ocelot的使用:API網關的應用
ASP.NET Core中Ocelot的使用:基于Spring Cloud Netflix Eureka的動態路由
ASP.NET Core中Ocelot的使用:基于服務發現的負載均衡
【.NET Core項目實戰-統一認證平臺】第一章 功能及架構分析
定制Ocelot來滿足需求
【.NET Core項目實戰-統一認證平臺】第三章 網關篇-數據庫存儲配置(1)
【.NET Core項目實戰-統一認證平臺】第四章 網關篇-數據庫存儲配置(2)
【.NET Core項目實戰-統一認證平臺】第五章 網關篇-自定義緩存Redis
【.NET Core項目實戰-統一認證平臺】第六章 網關篇-自定義客戶端授權
原文地址:https://www.cnblogs.com/jackcao/p/9987424.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DevOps/.NET 微服务 秋季分享
- 下一篇: .NET Core实战项目之CMS 第二