WebApiThrottle限流框架
2015-07-22 08:39
507 查看
ASP.NET Web API Throttling handler is designed to control the rate of requests that clients can make to a Web API based on IP address, client API key and request route. WebApiThrottle is compatible with Web API v2 and can be installed via NuGet, the package is available atnuget.org/packages/WebApiThrottle.
Web API throttling can be configured using the built-in
If from the same IP, in same second, you’ll make a call to
If you are self-hosting WebApi with Owin, then you’ll have to switch to
But if in the same second you call
If you want to apply limits to clients regardless of their IPs then you should set IpThrottling to false.
You can define endpoint rules by providing relative routes like
The endpoint throttling engine will search for the expression you’ve provided in the absolute URI,
if the expression is contained in the request route then the rule will be applied.
If two or more rules match the same URI then the lower limit will be applied.
and you’ve set a limit of one call per second, the minute, hour and day counters will only record the first call, the one that wasn’t blocked.
If you want rejected requests to count towards the other limits, you’ll have to set
Config example (policyType values are 1 – IP, 2 – ClientKey, 3 – Endpoint):
If your API key is stored differently, you can override the
Velocity, MemCache or a NoSQL database, all you have to do is create your own repository by implementing the IThrottleRepository interface.
Logging implementation example with ITraceWriter
Logging usage example with SystemDiagnosticsTraceWriter
Web API throttling can be configured using the built-in
ThrottlePolicy. You can set multiple limits for different scenarios like allowing an IP or Client to make a maximum number of calls per second, per minute, per hour or even per day. You can define these limits to address all requests made to an API or you can scope the limits to each API route.
Global throttling based on IP
The setup bellow will limit the number of requests originated from the same IP.If from the same IP, in same second, you’ll make a call to
api/valuesand
api/values/1the last call will get blocked.
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000) { IpThrottling = true }, Repository = new CacheRepository() }); } }
If you are self-hosting WebApi with Owin, then you’ll have to switch to
MemoryCacheRepositorythat uses the runtime memory cache instead of
CacheRepositorythat uses ASP.NET cache.
public class Startup { public void Configuration(IAppBuilder appBuilder) { // Configure Web API for self-host. HttpConfiguration config = new HttpConfiguration(); //Register throttling handler config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000) { IpThrottling = true }, Repository = new MemoryCacheRepository() }); appBuilder.UseWebApi(config); } }
Endpoint throttling based on IP
If, from the same IP, in the same second, you’ll make two calls toapi/values, the last call will get blocked.
But if in the same second you call
api/values/1too, the request will go through because it’s a different route.
config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository() });
Endpoint throttling based on IP and Client Key
If a client (identified by an unique API key) from the same IP, in the same second, makes two calls toapi/values, then the last call will get blocked.
If you want to apply limits to clients regardless of their IPs then you should set IpThrottling to false.
config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository() });
IP and/or Client Key White-listing
If requests are initiated from a white-listed IP or Client, then the throttling policy will not be applied and the requests will not get stored. The IP white-list supports IP v4 and v6 ranges like “192.168.0.0/24″, “fe80::/10″ and “192.168.0.0-192.168.0.255″ for more information check jsakamoto/ipaddressrange.config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 2, perMinute: 60) { IpThrottling = true, IpWhitelist = new List<string> { "::1", "192.168.0.0/24" }, ClientThrottling = true, ClientWhitelist = new List<string> { "admin-key" } }, Repository = new CacheRepository() });
IP and/or Client Key custom rate limits
You can define custom limits for known IPs or Client Keys, these limits will override the default ones. Be aware that a custom limit will only work if you have defined a global counterpart.config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500) { IpThrottling = true, IpRules = new Dictionary<string, RateLimits> { { "192.168.1.1", new RateLimits { PerSecond = 2 } }, { "192.168.2.0/24", new RateLimits { PerMinute = 30 } } }, ClientThrottling = true, ClientRules = new Dictionary<string, RateLimits> { { "api-client-key-1", new RateLimits { PerMinute = 40 } }, { "api-client-key-9", new RateLimits { PerDay = 2000 } } } }, Repository = new CacheRepository() });
Endpoint custom rate limits
You can also define custom limits for certain routes, these limits will override the default ones.You can define endpoint rules by providing relative routes like
api/entry/1or just a URL segment like
/entry/.
The endpoint throttling engine will search for the expression you’ve provided in the absolute URI,
if the expression is contained in the request route then the rule will be applied.
If two or more rules match the same URI then the lower limit will be applied.
config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true, EndpointRules = new Dictionary<string, RateLimits> { { "api/search", new RateLimits { PerScond = 10, PerMinute = 100, PerHour = 1000 } } } }, Repository = new CacheRepository() });
Stack rejected requests
By default, rejected calls are not added to the throttle counter. If a client makes 3 requests per secondand you’ve set a limit of one call per second, the minute, hour and day counters will only record the first call, the one that wasn’t blocked.
If you want rejected requests to count towards the other limits, you’ll have to set
StackBlockedRequeststo true.
config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true, StackBlockedRequests = true }, Repository = new CacheRepository() });
Define rate limits in web.config or app.config
WebApiThrottle comes with a custom configuration section that lets you define the throttle policy as xml.config.MessageHandlers.Add(new ThrottlingHandler() { Policy = ThrottlePolicy.FromStore(new PolicyConfigurationProvider()), Repository = new CacheRepository() });
Config example (policyType values are 1 – IP, 2 – ClientKey, 3 – Endpoint):
<configuration> <configSections> <section name="throttlePolicy" type="WebApiThrottle.ThrottlePolicyConfiguration, WebApiThrottle" /> </configSections> <throttlePolicy limitPerSecond="1" limitPerMinute="10" limitPerHour="30" limitPerDay="300" limitPerWeek ="1500" ipThrottling="true" clientThrottling="true" endpointThrottling="true"> <rules> <add policyType="1" entry="::1/10" limitPerSecond="2" limitPerMinute="15"/> <add policyType="1" entry="192.168.2.1" limitPerMinute="12" /> <add policyType="2" entry="api-client-key-1" limitPerHour="60" /> <add policyType="3" entry="api/values" limitPerDay="120" /> </rules> <whitelists> <add policyType="1" entry="127.0.0.1" /> <add policyType="1" entry="192.168.0.0/24" /> <add policyType="2" entry="api-admin-key" /> </whitelists> </throttlePolicy> </configuration>
Retrieving API Client Key
By default, the ThrottlingHandler retrieves the client API key from the “Authorization-Token” request header value.If your API key is stored differently, you can override the
ThrottlingHandler.SetIndentityfunction and specify your own retrieval method.
public class CustomThrottlingHandler : ThrottlingHandler { protected override RequestIndentity SetIndentity(HttpRequestMessage request) { return new RequestIndentity() { ClientKey = request.Headers.GetValues("Authorization-Key").First(), ClientIp = base.GetClientIp(request).ToString(), Endpoint = request.RequestUri.AbsolutePath }; } }
Storing throttle metrics
WebApiThrottle stores all request data in-memory using ASP.NET Cache when hosted in IIS or Runtime MemoryCache when self-hosted with Owin. If you want to change the storage toVelocity, MemCache or a NoSQL database, all you have to do is create your own repository by implementing the IThrottleRepository interface.
public interface IThrottleRepository { bool Any(string id); ThrottleCounter? FirstOrDefault(string id); void Save(string id, ThrottleCounter throttleCounter, TimeSpan expirationTime); void Remove(string id); void Clear(); }
Logging throttled requests
If you want to log throttled requests you’ll have to implement IThrottleLogger interface and provide it to the ThrottlingHandler.public interface IThrottleLogger { void Log(ThrottleLogEntry entry); }
Logging implementation example with ITraceWriter
public class TracingThrottleLogger : IThrottleLogger { private readonly ITraceWriter traceWriter; public TracingThrottleLogger(ITraceWriter traceWriter) { this.traceWriter = traceWriter; } public void Log(ThrottleLogEntry entry) { if (null != traceWriter) { traceWriter.Info(entry.Request, "WebApiThrottle", "{0} Request {1} from {2} has been throttled (blocked), quota {3}/{4} exceeded by {5}", entry.LogDate, entry.RequestId, entry.ClientIp, entry.RateLimit, entry.RateLimitPeriod, entry.TotalRequests); } } }
Logging usage example with SystemDiagnosticsTraceWriter
var traceWriter = new SystemDiagnosticsTraceWriter() { IsVerbose = true }; config.Services.Replace(typeof(ITraceWriter), traceWriter); config.EnableSystemDiagnosticsTracing(); config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository(), Logger = new TracingThrottleLogger() });
About
WebApiThrottle is open sourced and MIT licensed, the project is hosted on GitHub atgithub.com/stefanprodan/WebApiThrottle, for questions regarding throttling or any problems you’ve encounter please submit an issue on GitHub.相关文章推荐
- 【从零单排之微软面试100题系列】18之约瑟夫环问题
- C语言及OC语言初期学习心得
- 多线程中使用HIBERNATE,解决NO SESSION 问题
- a装笔记
- POJ 3660 Cow Contest (Floyd)
- html页面的各种标签的id不能相同
- 【Maven】Project configuration is not up-to-date with pom.xml错误解决方法
- 长微博生成(将html转化为图片)原理浅析
- ConcurrentHashMap实现原理--转载
- Python的包管理工具--PIP安装使用
- Canvas arcTo绘制圆弧
- 硬币的问题
- 表单javascript checkbox全选 反选 全不选
- 开源 java CMS - FreeCMS2.3会员我的评论
- 暑假集训第二周——递推 X - 毛毛虫走路
- 杭电 2089 不要62
- poj 2752 Seek the Name, Seek the Fame (KMP纯模版)
- 用jquery怎么实现点击显示,再一次点击隐藏
- iOS总结控件二(UIButton)
- 汇编中以bit为单位的比较