rate-limiter-flexible
Advanced tools
Comparing version 0.7.0 to 0.8.0
const RateLimiterRedis = require('./lib/RateLimiterRedis'); | ||
const { RateLimiterClusterMaster, RateLimiterCluster } = require('./lib/RateLimiterCluster'); | ||
const RateLimiterMemory = require('./lib/RateLimiterMemory'); | ||
@@ -6,3 +7,5 @@ | ||
RateLimiterRedis, | ||
RateLimiterMemory | ||
}; | ||
RateLimiterMemory, | ||
RateLimiterClusterMaster, | ||
RateLimiterCluster, | ||
}; |
{ | ||
"name": "rate-limiter-flexible", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"description": "Flexible API rate limiter backed by Redis for distributed node.js applications", | ||
@@ -31,3 +31,3 @@ "main": "index.js", | ||
"engines": { | ||
"node": "^10.0.0" | ||
"node": "^6.0.0" | ||
}, | ||
@@ -34,0 +34,0 @@ "devDependencies": { |
[![Build Status](https://travis-ci.org/animir/node-rate-limiter-flexible.png)](https://travis-ci.org/animir/node-rate-limiter-flexible) | ||
[![Coverage Status](https://coveralls.io/repos/animir/node-rate-limiter-flexible/badge.svg?branch=master)](https://coveralls.io/r/animir/node-rate-limiter-flexible?branch=master) | ||
[![npm version](https://badge.fury.io/js/rate-limiter-flexible.svg)](https://www.npmjs.com/package/rate-limiter-flexible) | ||
[![node version][node-image]][node-url] | ||
@@ -10,3 +11,4 @@ | ||
Flexible rate limiter and DDoS protector with Redis as broker allows to control requests rate in cluster or distributed environment. | ||
Flexible rate limiter and anti-DDoS protector works in process | ||
_Memory_, _Cluster_ or _Redis_ allows to control requests rate in single process or distributed environment. | ||
@@ -19,2 +21,3 @@ It uses **fixed window** as it is much faster than rolling window. | ||
* backed on native Promises | ||
* works in Cluster without additional software | ||
* actions can be done evenly over duration window to cut off picks | ||
@@ -29,33 +32,22 @@ * no race conditions | ||
Endpoint is simple Express 4.x route launched in `node:latest` and `redis:alpine` Docker containers by PM2 with 4 workers | ||
By `bombardier -c 1000 -l -d 10s -r 2500 -t 5s http://127.0.0.1:3000/pricing` | ||
Test with 1000 concurrent requests with maximum 2500 requests per sec during 10 seconds | ||
```text | ||
Statistics Avg Stdev Max | ||
Reqs/sec 2491.79 801.92 9497.25 | ||
Latency 8.62ms 11.69ms 177.96ms | ||
Reqs/sec 1994.83 439.72 5377.15 | ||
Latency 6.09ms 5.06ms 88.44ms | ||
Latency Distribution | ||
50% 5.41ms | ||
75% 7.65ms | ||
90% 15.07ms | ||
95% 27.24ms | ||
99% 70.85ms | ||
50% 4.98ms | ||
75% 6.65ms | ||
90% 9.33ms | ||
95% 13.65ms | ||
99% 34.27ms | ||
HTTP codes: | ||
1xx - 0, 2xx - 25025, 3xx - 0, 4xx - 0, 5xx - 0 | ||
others - 0 | ||
1xx - 0, 2xx - 59997, 3xx - 0, 4xx - 0, 5xx - 0 | ||
``` | ||
Endpoint is simple Express 4.x route launched in `node:latest` and `redis:alpine` Docker containers by PM2 with 4 workers | ||
Endpoint is limited by `RateLimiterRedis` with config: | ||
```javascript | ||
new RateLimiterRedis( | ||
{ | ||
redis: redisClient, | ||
points: 1000, | ||
duration: 1, | ||
}, | ||
); | ||
``` | ||
Note: Performance will be much better on real servers, as for this benchmark everything was launched on one machine | ||
@@ -90,2 +82,4 @@ | ||
execEvenly: false, | ||
// Redis specific | ||
blockOnPointsConsumed: 10, // If 10 points consumed in current duration | ||
@@ -131,2 +125,36 @@ blockDuration: 30, // block for 30 seconds in current process memory | ||
### RateLimiterCluster | ||
Note: it doesn't work with PM2 yet | ||
RateLimiterCluster performs limiting using IPC. | ||
Each request is sent to master process, which handles all the limits, then master send results back to worker. | ||
[See RateLimiterCluster benchmark and detailed description here](https://github.com/animir/node-rate-limiter-flexible/blob/master/CLUSTER.md) | ||
```javascript | ||
const cluster = require('cluster'); | ||
const numCPUs = require('os').cpus().length; | ||
const { RateLimiterClusterMaster, RateLimiterCluster } = require('rate-limiter-flexible'); | ||
if (cluster.isMaster) { | ||
// Doesn't require any options, it is only storage and messages handler | ||
new RateLimiterClusterMaster(); | ||
for (let i = 0; i < numCPUs; i++) { | ||
cluster.fork(); | ||
} | ||
} else { | ||
const rateLimiter = new RateLimiterCluster({ | ||
keyPrefix: 'myclusterlimiter', // Must be unique for each limiter | ||
points: 100, | ||
duration: 1, | ||
timeoutMs: 3000 // Promise is rejected, if master doesn't answer for 3 secs | ||
}); | ||
// Usage is the same as for RateLimiterRedis | ||
} | ||
``` | ||
### RateLimiterMemory | ||
@@ -164,2 +192,4 @@ | ||
#### Options specific to Redis | ||
* `blockOnPointsConsumed` `Default: 0` Against DDoS attacks. Blocked key isn't checked by requesting Redis. | ||
@@ -181,3 +211,8 @@ Blocking works in **current process memory**. | ||
#### Options specific to Cluster | ||
* `timeoutMs` `Default: 5000` Timeout for communication between worker and master over IPC. | ||
If master doesn't response in time, promise is rejected with Error | ||
## API | ||
@@ -199,6 +234,7 @@ | ||
Returns Promise, which: | ||
* resolved when point(s) is consumed, so action can be done | ||
* only for RateLimiterRedis: rejected when some Redis error happened, where reject reason `rejRes` is Error object | ||
* rejected when there is no points to be consumed, where reject reason `rejRes` is `RateLimiterRes` object | ||
* rejected when key is blocked (if block strategy is set up), where reject reason `rejRes` is `RateLimiterRes` object | ||
* **resolved** when point(s) is consumed, so action can be done | ||
* only for RateLimiterRedis if `insuranceLimiter` isn't setup: **rejected** when some Redis error happened, where reject reason `rejRes` is Error object | ||
* only for RateLimiterCluster: **rejected** when `timeotMs` exceeded, where reject reason `rejRes` is Error object | ||
* **rejected** when there is no points to be consumed, where reject reason `rejRes` is `RateLimiterRes` object | ||
* **rejected** when key is blocked (if block strategy is set up), where reject reason `rejRes` is `RateLimiterRes` object | ||
@@ -231,2 +267,2 @@ Arguments: | ||
Appreciated, feel free! | ||
Appreciated, feel free! |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
119464
31
1418
260