{"id":1150,"date":"2025-05-27T14:47:52","date_gmt":"2025-05-27T06:47:52","guid":{"rendered":"https:\/\/www.hyy.net\/?p=1150"},"modified":"2025-05-27T14:47:52","modified_gmt":"2025-05-27T06:47:52","slug":"ultimate-asp-net-core-web-api-26-rate-limiting-and-throttling","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=1150","title":{"rendered":"Ultimate ASP.NET Core Web API 26 RATE LIMITING AND THROTTLING"},"content":{"rendered":"<p>26 RATE LIMITING AND THROTTLING<br \/>\n26 \u901f\u7387\u9650\u5236\u548c\u9650\u5236<\/p>\n<p>Rate Limiting allows us to protect our API against too many requests that can deteriorate our API\u2019s performance. API is going to reject requests that exceed the limit. Throttling queues exceeded requests for possible later processing. The API will eventually reject the request if processing cannot occur after a certain number of attempts.\u200c<br \/>\nRate Limiting \u4f7f\u6211\u4eec\u80fd\u591f\u4fdd\u62a4\u6211\u4eec\u7684 API \u514d\u53d7\u8fc7\u591a\u7684\u8bf7\u6c42\u7684\u5f71\u54cd\uff0c\u8fd9\u4e9b\u8bf7\u6c42\u53ef\u80fd\u4f1a\u964d\u4f4e API \u7684\u6027\u80fd\u3002API \u5c06\u62d2\u7edd\u8d85\u8fc7\u9650\u5236\u7684\u8bf7\u6c42\u3002\u9650\u5236\u961f\u5217\u8d85\u51fa\u4e86\u4ee5\u540e\u53ef\u80fd\u5904\u7406\u7684\u8bf7\u6c42\u3002\u5982\u679c\u5728\u4e00\u5b9a\u6b21\u6570\u7684\u5c1d\u8bd5\u540e\u65e0\u6cd5\u8fdb\u884c\u5904\u7406\uff0c\u5219 API \u6700\u7ec8\u5c06\u62d2\u7edd\u8be5\u8bf7\u6c42\u3002<\/p>\n<p>For example, we can configure our API to create a limitation of 100 requests\/hour per client. Or additionally, we can limit a client to the maximum of 1,000 requests\/day per IP and 100 requests\/hour. We can even limit the number of requests for a specific resource in our API; for example, 50 requests to api\/companies.<br \/>\n\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u5c06 API \u914d\u7f6e\u4e3a\u4e3a\u6bcf\u4e2a\u5ba2\u6237\u7aef\u521b\u5efa 100 \u4e2a\u8bf7\u6c42\/\u5c0f\u65f6\u7684\u9650\u5236\u3002\u6216\u8005\uff0c\u6211\u4eec\u53ef\u4ee5\u5c06\u5ba2\u6237\u7aef\u9650\u5236\u4e3a\u6bcf\u4e2a IP \u6bcf\u5929\u6700\u591a 1000 \u4e2a\u8bf7\u6c42\uff0c\u6bcf\u5c0f\u65f6\u6700\u591a 100 \u4e2a\u8bf7\u6c42\u3002\u6211\u4eec\u751a\u81f3\u53ef\u4ee5\u5728 API \u4e2d\u9650\u5236\u5bf9\u7279\u5b9a\u8d44\u6e90\u7684\u8bf7\u6c42\u6570\u91cf;\u4f8b\u5982\uff0c\u5bf9 API\/Companies \u7684 50 \u4e2a\u8bf7\u6c42\u3002<\/p>\n<p>To provide information about rate limiting, we use the response headers. They are separated between Allowed requests, which all start with the X- Rate-Limit and Disallowed requests.<br \/>\n\u4e3a\u4e86\u63d0\u4f9b\u6709\u5173\u901f\u7387\u9650\u5236\u7684\u4fe1\u606f\uff0c\u6211\u4eec\u4f7f\u7528\u54cd\u5e94\u6807\u5934\u3002\u5b83\u4eec\u5206\u4e3a Allowed \u8bf7\u6c42\uff0c\u8fd9\u4e9b\u8bf7\u6c42\u90fd\u4ee5 X-Rate-Limit \u548c Disallowed \u8bf7\u6c42\u5f00\u5934\u3002<\/p>\n<p>The Allowed requests header contains the following information :<br \/>\nAllowed requests \u6807\u5934\u5305\u542b\u4ee5\u4e0b\u4fe1\u606f\uff1a<\/p>\n<p>\u2022 X-Rate-Limit-Limit \u2013 rate limit period.<br \/>\nX-Rate-Limit-Limit \u2013 \u901f\u7387\u9650\u5236\u671f\u3002<\/p>\n<p>\u2022 X-Rate-Limit-Remaining \u2013 number of remaining requests.<br \/>\nX-Rate-Limit-Remaining \u2013 \u5269\u4f59\u8bf7\u6c42\u6570\u3002<\/p>\n<p>\u2022 X-Rate-Limit-Reset \u2013 date\/time information about resetting the request limit.<br \/>\nX-Rate-Limit-Reset \u2013 \u6709\u5173\u91cd\u7f6e\u8bf7\u6c42\u9650\u5236\u7684\u65e5\u671f\/\u65f6\u95f4\u4fe1\u606f\u3002<\/p>\n<p>For the disallowed requests, we use a 429 status code; that stands for too many requests. This header may include the Retry-After response header and should explain details in the response body.<br \/>\n\u5bf9\u4e8e\u4e0d\u5141\u8bb8\u7684\u8bf7\u6c42\uff0c\u6211\u4eec\u4f7f\u7528 429 \u72b6\u6001\u4ee3\u7801;\u8fd9\u4ee3\u8868\u8bf7\u6c42\u592a\u591a\u3002\u6b64\u6807\u5934\u53ef\u80fd\u5305\u62ec Retry-After \u54cd\u5e94\u6807\u5934\uff0c\u5e76\u5e94\u5728\u54cd\u5e94\u6b63\u6587\u4e2d\u8bf4\u660e\u8be6\u7ec6\u4fe1\u606f\u3002<\/p>\n<h2>26.1 Implementing Rate Limiting<\/h2>\n<p>26.1 \u5b9e\u73b0\u901f\u7387\u9650\u5236<\/p>\n<p>To start, we have to install the AspNetCoreRateLimit library in the main project:\u200c<br \/>\n\u9996\u5148\uff0c\u6211\u4eec\u5fc5\u987b\u5728\u4e3b\u9879\u76ee\u4e2d\u5b89\u88c5 AspNetCoreRateLimit \u5e93\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/2601.jpg\" alt=\"alt text\" \/><\/p>\n<p>Then, we have to add it to the service collection. This library uses a memory cache to store its counters and rules. Therefore, we have to add the MemoryCache to the service collection as well.<br \/>\n\u7136\u540e\uff0c\u6211\u4eec\u5fc5\u987b\u5c06\u5176\u6dfb\u52a0\u5230\u670d\u52a1\u96c6\u5408\u4e2d\u3002\u6b64\u5e93\u4f7f\u7528\u5185\u5b58\u7f13\u5b58\u6765\u5b58\u50a8\u5176\u8ba1\u6570\u5668\u548c\u89c4\u5219\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u8fd8\u5fc5\u987b\u5c06 MemoryCache \u6dfb\u52a0\u5230\u670d\u52a1\u96c6\u5408\u4e2d\u3002<\/p>\n<p>That said, let\u2019s add the MemoryCache:<br \/>\n\u4e5f\u5c31\u662f\u8bf4\uff0c\u8ba9\u6211\u4eec\u6dfb\u52a0 MemoryCache\uff1a<\/p>\n<pre><code>builder.Services.AddMemoryCache();<\/code><\/pre>\n<p>After that, we are going to create another extension method in the ServiceExtensions class:<br \/>\n\u4e4b\u540e\uff0c\u6211\u4eec\u5c06\u5728 ServiceExtensions \u7c7b\u4e2d\u521b\u5efa\u53e6\u4e00\u4e2a\u6269\u5c55\u65b9\u6cd5\uff1a<\/p>\n<pre><code>public static void ConfigureRateLimitingOptions(this IServiceCollection services) { var rateLimitRules = new List&lt;RateLimitRule&gt; { new RateLimitRule { Endpoint = &quot;*&quot;, Limit = 3, Period = &quot;5m&quot; } }; services.Configure&lt;IpRateLimitOptions&gt;(opt =&gt; { opt.GeneralRules = rateLimitRules; }); services.AddSingleton&lt;IRateLimitCounterStore, MemoryCacheRateLimitCounterStore&gt;(); services.AddSingleton&lt;IIpPolicyStore, MemoryCacheIpPolicyStore&gt;(); services.AddSingleton&lt;IRateLimitConfiguration, RateLimitConfiguration&gt;(); services.AddSingleton&lt;IProcessingStrategy, AsyncKeyLockProcessingStrategy&gt;(); }<\/code><\/pre>\n<p>We create a rate limit rules first, for now just one, stating that three requests are allowed in a five-minute period for any endpoint in our API. Then, we configure IpRateLimitOptions to add the created rule. Finally, we have to register rate limit stores, configuration, and processing strategy as a singleton. They serve the purpose of storing rate limit counters and policies as well as adding configuration.<br \/>\n\u6211\u4eec\u9996\u5148\u521b\u5efa\u4e00\u4e2a\u901f\u7387\u9650\u5236\u89c4\u5219\uff0c\u73b0\u5728\u53ea\u6709\u4e00\u4e2a\uff0c\u89c4\u5b9a\u5728 5 \u5206\u949f\u5185\u5141\u8bb8\u5bf9 API \u4e2d\u7684\u4efb\u4f55\u7ec8\u7aef\u8282\u70b9\u53d1\u51fa\u4e09\u4e2a\u8bf7\u6c42\u3002\u7136\u540e\uff0c\u6211\u4eec\u914d\u7f6e IpRateLimitOptions \u4ee5\u6dfb\u52a0\u521b\u5efa\u7684\u89c4\u5219\u3002\u6700\u540e\uff0c\u6211\u4eec\u5fc5\u987b\u5c06 Rate limit \u5b58\u50a8\u3001\u914d\u7f6e\u548c\u5904\u7406\u7b56\u7565\u6ce8\u518c\u4e3a\u5355\u4f8b\u3002\u5b83\u4eec\u7528\u4e8e\u5b58\u50a8\u901f\u7387\u9650\u5236\u8ba1\u6570\u5668\u548c\u7b56\u7565\u4ee5\u53ca\u6dfb\u52a0\u914d\u7f6e\u3002<\/p>\n<p>Now, we have to modify the Program class again:<br \/>\n\u73b0\u5728\uff0c\u6211\u4eec\u5fc5\u987b\u518d\u6b21\u4fee\u6539 Program \u7c7b\uff1a<\/p>\n<pre><code>builder.Services.ConfigureRateLimitingOptions(); \nbuilder.Services.AddHttpContextAccessor();\nbuilder.Services.AddMemoryCache();<\/code><\/pre>\n<p>Finally, we have to add it to the request pipeline:<br \/>\n\u6700\u540e\uff0c\u6211\u4eec\u5fc5\u987b\u5c06\u5176\u6dfb\u52a0\u5230\u8bf7\u6c42\u7ba1\u9053\u4e2d\uff1a<\/p>\n<pre><code>app.UseIpRateLimiting();\napp.UseCors(&quot;CorsPolicy&quot;);<\/code><\/pre>\n<p>And that is it. We can test this now:<br \/>\n\u5c31\u662f\u8fd9\u6837\u3002\u6211\u4eec\u73b0\u5728\u53ef\u4ee5\u6d4b\u8bd5\u4e00\u4e0b\uff1a<br \/>\n<a href=\"https:\/\/localhost:5001\/api\/companies\">https:\/\/localhost:5001\/api\/companies<\/a><\/p>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/2602.jpg\" alt=\"alt text\" \/><\/p>\n<p>So, we can see that we have two requests remaining and the time to reset the rule. If we send an additional three requests in the five-minute period of time, we are going to get a different response:<br \/>\n\u56e0\u6b64\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u8fd8\u5269\u4e0b\u4e24\u4e2a\u8bf7\u6c42\u548c\u91cd\u7f6e\u89c4\u5219\u7684\u65f6\u95f4\u3002\u5982\u679c\u6211\u4eec\u5728 5 \u5206\u949f\u5185\u989d\u5916\u53d1\u9001 3 \u4e2a\u8bf7\u6c42\uff0c\u6211\u4eec\u5c06\u5f97\u5230\u4e0d\u540c\u7684\u54cd\u5e94\uff1a<br \/>\n<a href=\"https:\/\/localhost:5001\/api\/companies\">https:\/\/localhost:5001\/api\/companies<\/a><\/p>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/2603.jpg\" alt=\"alt text\" \/><\/p>\n<p>The status code is 429 Too Many Requests and we have the Retry-After header.<br \/>\n\u72b6\u6001\u4ee3\u7801\u4e3a 429 Too Many Requests\uff0c\u6211\u4eec\u6709 Retry-After \u6807\u5934\u3002<\/p>\n<p>We can inspect the GET\u4e3b\u4f53 as well:<br \/>\n\u6211\u4eec\u4e5f\u53ef\u4ee5\u68c0\u67e5\u8eab\u4f53\uff1a<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\">https:\/\/localhost:5001\/api\/companies<\/a><\/p>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/2604.jpg\" alt=\"alt text\" \/><\/p>\n<p>So, our rate limiting works.<br \/>\n\u56e0\u6b64\uff0c\u6211\u4eec\u7684\u901f\u7387\u9650\u5236\u6709\u6548\u3002<\/p>\n<p>There are a lot of options that can be configured with Rate Limiting and you can read more about them on the AspNetCoreRateLimit GitHub page.<br \/>\n\u6709\u5f88\u591a\u9009\u9879\u53ef\u4ee5\u4f7f\u7528 Rate Limiting \u8fdb\u884c\u914d\u7f6e\uff0c\u60a8\u53ef\u4ee5\u5728 AspNetCoreRateLimit GitHub \u9875\u9762\u4e0a\u9605\u8bfb\u6709\u5173\u5b83\u4eec\u7684\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>26 RATE LIMITING AND THROTTLING 26 \u901f\u7387\u9650\u5236\u548c\u9650\u5236 Rate Limiting allows us to protect our API against too many requests that can deteriorate our API\u2019s performance. API is going to reject requests that exceed the limit. Throttling queues exceeded requests for possible later processing. The API will eventually reject the request if processing cannot occur after [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1150","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/1150","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1150"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/1150\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1150"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1150"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1150"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}