private RateLimitProcessor <SimulationRequest> GetLeakyBucketProcessor(string storageType, int limitNumber) { IRateLimitStorage storage = memoryStorage; if (storageType == "redis") { storage = redisStorage; } var leakyBucketRules = new LeakyBucketRateLimitRule <SimulationRequest>[] { new LeakyBucketRateLimitRule <SimulationRequest>(limitNumber, 100, TimeSpan.FromSeconds(1)) { Id = Guid.NewGuid().ToString(), LockSeconds = 1, ExtractTarget = (request) => { return(request.RequestResource); }, CheckRuleMatching = (request) => { return(true); }, } }; return(new RateLimitProcessor <SimulationRequest> .Builder() .WithAlgorithm(new LeakyBucketAlgorithm <SimulationRequest>(leakyBucketRules)) .WithStorage(storage) .WithError(new RateLimitError() { Code = 429, }) .Build()); }
/// <summary> /// /// </summary> /// <param name="target"></param> /// <param name="storage"></param> /// <param name="rule"></param> /// <returns></returns> protected override async Task <bool> CheckSingleRuleAsync(string target, IRateLimitStorage storage, RateLimitRule <TRequest> rule) { var currentRule = rule as SlidingWindowRateLimitRule <TRequest>; var result = await storage.SlidingWindowIncrementAsync(target, 1, currentRule.StatWindow, currentRule.StatPeriod, currentRule.PeriodNumber, currentRule.LimitNumber, currentRule.LockSeconds); Debug.WriteLine("check result:" + result.Item1 + "," + result.Item2); return(result.Item1); }
/// <summary> /// /// </summary> /// <param name="target"></param> /// <param name="storage"></param> /// <param name="rule"></param> /// <returns></returns> protected override async Task <bool> CheckSingleRuleAsync(string target, IRateLimitStorage storage, RateLimitRule <TRequest> rule) { var currentRule = rule as TokenBucketRateLimitRule <TRequest>; var result = await storage.TokenBucketDecrementAsync(target, 1, currentRule.Capacity, (int)currentRule.InflowUnit.TotalMilliseconds, currentRule.InflowQuantityPerUnit, currentRule.LockSeconds); Debug.WriteLine("check result:" + result.Item1 + "," + result.Item2); return(result.Item1); }
/// <summary> /// /// </summary> /// <param name="target"></param> /// <param name="storage"></param> /// <param name="rule"></param> /// <returns></returns> protected override async Task <bool> CheckSingleRuleAsync(string target, IRateLimitStorage storage, RateLimitRule <TRequest> rule) { var currentRule = rule as FixedWindowRateLimitRule <TRequest>; var countAmount = 1; var expireTimeSpan = currentRule.StatWindow; var result = await storage.FixedWindowIncrementAsync(target, countAmount, expireTimeSpan, currentRule.LimitNumber, rule.LockSeconds); return(result.Item1); }
/// <summary> /// check single rule for target /// </summary> /// <param name="target"></param> /// <param name="storage"></param> /// <param name="rule"></param> /// <returns></returns> protected override bool CheckSingleRule(string target, IRateLimitStorage storage, RateLimitRule <TRequest> rule) { var currentRule = rule as LeakyBucketRateLimitRule <TRequest>; var result = storage.LeakyBucketIncrement(target, 1, currentRule.Capacity, (int)currentRule.OutflowUnit.TotalMilliseconds, currentRule.OutflowQuantityPerUnit, currentRule.LockSeconds); Debug.WriteLine("check result:" + result.Item1 + "," + result.Item2); return(result.Item1); }
/// <summary> /// Build a instance of RateLimitProcessor with some configurations /// </summary> /// <returns></returns> public RateLimitProcessor <TRequest> Build() { if (_storage == null) { _storage = new InProcessMemoryStorage(); } if (_algorithm == null) { throw new ArgumentNullException("the algorithm can not be null."); } if (_error == null) { _error = new RateLimitError(); } return(new RateLimitProcessor <TRequest>(_storage, _algorithm, _error)); }
/// <summary> /// check a request for rate limit /// </summary> /// <param name="request">a request</param> /// <param name="storage">a instance of IRateLimitStorage</param> /// <returns>the list of check result</returns> public List <RateLimitCheckResult <TRequest> > Check(TRequest request, IRateLimitStorage storage) { List <RateLimitCheckResult <TRequest> > results = new List <RateLimitCheckResult <TRequest> >(); if (_updatable) { try { _lock.EnterReadLock(); CheckAllRules(request, storage, results); } finally { _lock.ExitReadLock(); } } else { CheckAllRules(request, storage, results); } return(results); }
private void CheckAllRules(TRequest request, IRateLimitStorage storage, List <RateLimitCheckResult <TRequest> > results) { foreach (var rule in _rules) { if (rule.CheckRuleMatching(request)) { var target = rule.ExtractTarget(request); if (string.IsNullOrWhiteSpace(target)) { throw new NotSupportedException("不支持Target为空"); } target = string.Concat(rule.Id, "-", target); // target for rule bool result = CheckSingleRule(target, storage, rule); results.Add(new RateLimitCheckResult <TRequest>() { Rule = rule, Target = target, IsLimit = result }); } } }
private RateLimitProcessor <SimulationRequest> GetFixedWindowProcessor(string storageType, int limitNumber) { IRateLimitStorage storage = memoryStorage; if (storageType == "redis") { storage = redisStorage; } var fixedWindowRules = new FixedWindowRateLimitRule <SimulationRequest>[] { new FixedWindowRateLimitRule <SimulationRequest>() { Id = Guid.NewGuid().ToString(), StatWindow = TimeSpan.FromSeconds(1), LimitNumber = limitNumber, ExtractTarget = (request) => { return(request.RequestResource); }, CheckRuleMatching = (request) => { return(true); }, } }; return(new RateLimitProcessor <SimulationRequest> .Builder() .WithAlgorithm(new FixedWindowAlgorithm <SimulationRequest>(fixedWindowRules)) .WithStorage(storage) .WithError(new RateLimitError() { Code = 429, }) .Build()); }
/// <summary> /// Sets a instance of IRateLimitStorage /// </summary> /// <param name="storage"></param> /// <returns></returns> public Builder WithStorage(IRateLimitStorage storage) { _storage = storage; return(this); }
/// <summary> /// create a new instance /// </summary> /// <param name="storage"></param> /// <param name="algorithm"></param> /// <param name="error"></param> private RateLimitProcessor(IRateLimitStorage storage, IRateLimitAlgorithm <TRequest> algorithm, RateLimitError error) { _algorithm = algorithm; _storage = storage; _error = error; }
/// <summary> /// /// </summary> /// <param name="target"></param> /// <param name="storage"></param> /// <param name="rule"></param> /// <returns></returns> protected abstract Task <bool> CheckSingleRuleAsync(string target, IRateLimitStorage storage, RateLimitRule <TRequest> rule);
/// <summary> /// /// </summary> /// <param name="target"></param> /// <param name="storage"></param> /// <param name="rule"></param> /// <returns></returns> protected abstract bool CheckSingleRule(string target, IRateLimitStorage storage, RateLimitRule <TRequest> rule);
public void GlobalSetup() { memoryStorage = new InProcessMemoryStorage(); redisStorage = new RedisStorage(StackExchange.Redis.ConnectionMultiplexer.Connect("127.0.0.1")); }