博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebApiThrottle限流框架
阅读量:5933 次
发布时间:2019-06-19

本文共 9778 字,大约阅读时间需要 32 分钟。

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 at.

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/values and api/values/1 the 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 MemoryCacheRepository that uses the runtime memory cache instead of CacheRepository that 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 to api/values, the last call will get blocked.

But if in the same second you call api/values/1 too, 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 .

config.MessageHandlers.Add(new ThrottlingHandler(){    Policy = new ThrottlePolicy(perSecond: 2, perMinute: 60)    {        IpThrottling = true,        IpWhitelist = new List
{ "::1", "192.168.0.0/24" }, ClientThrottling = true, ClientWhitelist = new List
{ "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
{ { "192.168.1.1", new RateLimits { PerSecond = 2 } }, { "192.168.2.0/24", new RateLimits { PerMinute = 30 } } }, ClientThrottling = true, ClientRules = new Dictionary
{ { "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/1 or 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
{ { "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 second

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 setStackBlockedRequests to 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):

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.SetIndentity function 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 to

Velocity, 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 at, for questions regarding throttling or any problems you’ve encounter please submit an issue on GitHub.

转载地址:http://zvctx.baihongyu.com/

你可能感兴趣的文章
程序猿给马云提建议 阿里DT时代怎么走
查看>>
淘宝微信如何进入微信推广?
查看>>
极速闪存IBM FlashSystem一马当先
查看>>
王健林:没用的数据再大也照样死
查看>>
新华三Synergy塑合型基础架构为新经济提供强大引擎
查看>>
揭秘:海康威视的“棱镜门”不是弱密码问题
查看>>
数据中心停机中断真的是无法回避的现实吗?
查看>>
Linux基金会透露未来 Linux内核可能会引入形式验证
查看>>
用大数据失败案例的血泪教训来诉说8个不能犯的错误
查看>>
王垠:如何掌握所有的程序语言
查看>>
云如何帮助企业处理安全日志数据
查看>>
坐着编程变胖 站着编程伤膝盖
查看>>
“睡眠创业公司”——Casper意图颠覆床垫市场
查看>>
即将到来的高清视频时代,我们做好技术准备了吗?
查看>>
产品经理必会的五大数据分析模型
查看>>
MySpace出现史上最大规模数据泄露事件
查看>>
只要阅读两篇有关勒索软件的文章就可解锁!
查看>>
轻量级大规模机器学习算法库Fregata开源:快速,无需调参
查看>>
从蓝瘦“想哭”到 SELinux 看操作系统安全何在
查看>>
ISIS“摊上大事”,黑客组织“匿名者”发布仇杀令
查看>>