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