<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ASP.NET Core 中如何對不同類型的用戶進行區(qū)別限流

          共 4455字,需瀏覽 9分鐘

           ·

          2021-06-19 19:01


          前言


          老板提出了一個新需求,從某某天起,免費用戶每天只能查詢100次,收費用戶100W次。


          這是一個限流問題,聰明的你也一定想到了如何去做:記錄用戶每一天的查詢次數(shù),然后根據(jù)當前用戶的類型使用不同的數(shù)字做比較,超過指定的數(shù)字就返回錯誤。


          嗯,原理就是這么簡單。不過真正寫起來還要考慮更多問題:


          • 統(tǒng)計數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)是什么樣的?字典 or 行記錄?


          • 統(tǒng)計數(shù)據(jù)記錄到哪里?內(nèi)存 or MySQL or Redis?


          • 分布式應(yīng)用怎么精確計數(shù)?分布式鎖 or 隊列 or 事務(wù)?


          • 吞吐量比較大時如何扛得?。績?nèi)存 or Redis or 數(shù)據(jù)庫集群?


          • 這些數(shù)據(jù)要一直保留嗎?自動過期 or 定期清理?


          • 如何返回錯誤?自定義錯誤 or HTTP標準錯誤碼?


          自己去做這些事還是有點麻煩的,這里介紹一個ASP.NET Core的中間件來滿足這個限流需求:FireflySoft.RateLimit.AspNetCore。使用步驟如下:


          一、安裝Nuget包


          已經(jīng)發(fā)布到nuget.org,有多種安裝方式,選擇自己喜歡的就行了。


          包管理器命令:


          Install-Package FireflySoft.RateLimit.AspNetCore


          或者.NET命令:


          dotnet add package FireflySoft.RateLimit.AspNetCore


          或者項目文件直接添加:


          <ItemGroup>
          <PackageReference Include="FireflySoft.RateLimit.AspNetCore" Version="1.2.0" />
          </ItemGroup>


          二、使用中間件


          在Startup.Configure中使用中間件,演示代碼如下(下邊會有詳細說明):


          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
          ...
          app.UseRateLimit(new RateLimitProcessor<HttpContext>.Builder()
          .WithAlgorithm(new FixedWindowAlgorithm<HttpContext>( new[] {
          new FixedWindowRateLimitRule<HttpContext>()
          {
          Id = "1",
          ExtractTarget = context =>
          {
          // 這里假設(shè)用戶Id是從cookie中傳過來的,需根據(jù)實際情況獲取
          return context.Request.GetTypedHeaders().Get<string>("userId");
          },
          CheckRuleMatching = context =>
          {
          // 這里假設(shè)用戶類型是從cookie中傳過來的,實際可能需要根據(jù)用戶Id再去查詢
          // 0免費用戶 1收費用戶
          int userType = context.Request.GetTypedHeaders().Get<int>("userType");
          if(userType==0){
          return true;
          }
          return false;
          },
          Name="免費用戶限流規(guī)則",
          LimitNumber=100,
          StatWindow=TimeSpan.FromDays(1)
          },
          new FixedWindowRateLimitRule<HttpContext>()
          {
          Id = "2",
          ExtractTarget = context =>
          {
          // 這里假設(shè)用戶Id是從cookie中傳過來的,需根據(jù)實際情況獲取
          return context.Request.GetTypedHeaders().Get<string>("userId");
          },
          CheckRuleMatching = context =>
          {
          // 這里假設(shè)用戶類型是從cookie中傳過來的,實際可能需要根據(jù)用戶Id再去查詢
          // 0免費用戶 1收費用戶
          int userType = context.Request.GetTypedHeaders().Get<int>("userType");
          if(userType==1){
          return true;
          }
          return false;
          },
          Name="收費用戶限流規(guī)則",
          LimitNumber=1000000,
          StatWindow=TimeSpan.FromDays(1)
          }
          }))
          .WithError(new Core.RateLimitError()
          {
          Code=429,
          Message = "查詢數(shù)達到當天最大限制"
          })
          //.WithStorage(new RedisStorage(StackExchange.Redis.ConnectionMultiplexer.Connect("localhost")))
          .Build());
          ...
          }


          使用此中間件需要構(gòu)建一個名為RateLimitProcessor的限流處理器實例,指定限流處理的請求類型HttpContext,設(shè)置限流處理的三個方面:


          1、限流使用的算法以及對應(yīng)的規(guī)則


          限流算法,根據(jù)這個需求使用固定窗口算法就可以了,也稱為計數(shù)器算法。此中間件還提供了滑動窗口算法、漏桶算法、令牌桶算法,可以根據(jù)需要選擇。


          不同的限流算法有不同的限流規(guī)則類型,在這里使用的是固定窗口限流規(guī)則,針對免費用戶和收費用戶分別定義了兩個規(guī)則,注意其中的幾個參數(shù):


          • Id:在當前的版本中Id必須手動指定,并且不能重復。


          • ExtractTarget:傳遞一個方法用于從請求中提取限流目標,這里就是用戶Id。


          • CheckRuleMatching傳遞一個方法用于檢查當前請求是否適用當前規(guī)則,這里根據(jù)用戶類型進行判斷。


          • StatWindow是固定窗口的大小,是一個時間跨度,這里是1天。


          • LimitNumber是限流值,在StatWindow時間內(nèi)請求數(shù)超過它就會觸發(fā)限流。


          這里有兩個比較有意思的設(shè)置:ExtractTarget和CheckRuleMatching,他們共同作用,讓用戶可以完全自由的定制自己限流的目標和條件,無論是IP、ClientId或者Url。


          2、限流統(tǒng)計數(shù)據(jù)的持久化方式


          FireflySoft.RateLimit中的限流計數(shù)目前支持保存在內(nèi)存或者Redis中,也可以通過實現(xiàn)IRateLimitStorage來定義一個新的存儲器,不設(shè)置時默認為內(nèi)存存儲。


          對于只需要部署一份的程序,絕大部分情況下使用內(nèi)存就夠了;但是如果限流的時間窗口比較長,比如1小時限制300次,重啟就會丟失計數(shù),這可能是個風險,此時使用Redis會比較合適。對于分布式應(yīng)用,也建議使用Redis存儲。


          限流統(tǒng)計數(shù)據(jù)會根據(jù)限流時間窗口自動過期移除。


          3、被限流時的錯誤碼和消息


          默認限流錯誤Code是429,這個會作為HttpStatusCode返回;Message默認為null,你可以修改為自己的任意文字提示,這個會作為Http Body的內(nèi)容返回。


          以上就是使用FireflySoft.RateLimit.AspNetCore對不同類型的用戶進行區(qū)別限流的使用方法。


          如果覺得還是限制的有點死,比如返回錯誤信息部分,想返回一個json格式的錯誤消息,還可以使用FireflySoft.RateLimit.Core這個包來封裝自己的ASP.NET Core中間件。


          如果想在這個程序的基礎(chǔ)上再改造下,可以fork這個項目:https://github.com/bosima/FireflySoft.RateLimit

          轉(zhuǎn)自:波斯馬

          鏈接:cnblogs.com/bossma/p/asp-net-core


          回復 【關(guān)閉】關(guān)
          回復 【實戰(zhàn)】獲取20套實戰(zhàn)源碼
          回復 【被刪】
          回復 【訪客】
          回復 【小程序】學獲取15套【入門+實戰(zhàn)+賺錢】小程序源碼
          回復 【python】學微獲取全套0基礎(chǔ)Python知識手冊
          回復 【2019】獲取2019 .NET 開發(fā)者峰會資料PPT
          回復 【加群】加入dotnet微信交流群

          去TM收費,我要在線 Vip 視頻解析!


          被網(wǎng)易云刷屏的人格顏色測試,我來總結(jié)下……爆火,點擊查看>>>


          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  2018天天操 | 激情综合五月婷婷 | 青娱乐国产盛宴 | 國產精品77777777777 | 大香蕉性网 |