Verified Commit 094f6b5e authored by Martin Petráček's avatar Martin Petráček
Browse files

rate limiting configuration

parent 26314ac2
......@@ -26,6 +26,9 @@ authenticator_host: localhost
authenticator_port: 8888
fastpings:
0000000500000842
; rate limiter - bucket capacity
; actual capacity is rate_limit_number (specified for plugins) * this number
rate_limiter_bucket_capacity: 5
; The plugins to load follow. Each name is the class to load and instantiate.
......@@ -55,6 +58,10 @@ interval: 900 ; How often to store a snapshot, seconds.
aggregate_delay: 5 ; How long to wait for answers from clients before working on them.
[flow_plugin.FlowPlugin]
# number of messages that client is allowed to send...
rate_limit_number = 5
# ... in some interval [seconds]
rate_limit_interval = 60
[fwup_plugin.FWUpPlugin]
[refused_plugin.RefusedPlugin]
......@@ -64,6 +71,10 @@ send_limit = 3
undecided_limit = 50
timeout = 30000
max_age = 120000
# number of messages that client is allowed to send...
rate_limit_number = 5
# ... in some interval [seconds]
rate_limit_interval = 60
[fake_plugin.FakePlugin]
version = 1
......@@ -71,3 +82,8 @@ max_age = 60000
max_size = 2048
max_attempts = 2
throttle_holdback = 120000
# number of messages that client is allowed to send...
rate_limit_number = 5
# ... in some interval [seconds]
rate_limit_interval = 60
......@@ -90,7 +90,7 @@ class FakePlugin(plugin.Plugin):
def __init__(self, plugins, config):
plugin.Plugin.__init__(self, plugins)
self.__config = config
self.__rate_limiter = rate_limit.RateLimiter(100, 1000, 60) #maximum 100 (in average) records per 60 seconds (peak 1000)
self.__rate_limiter = rate_limit.RateLimiter(int(self.__config['rate_limit_number']), int(self.__config['rate_limit_interval']))
def name(self):
return 'Fake'
......
......@@ -227,11 +227,12 @@ class FlowPlugin(plugin.Plugin, diff_addr_store.DiffAddrStore):
"""
def __init__(self, plugins, config):
plugin.Plugin.__init__(self, plugins)
self.__config = config
self.__top_filter_cache = {}
diff_addr_store.DiffAddrStore.__init__(self, logger, "flow", "flow_filters", "filter")
self.__delayed_config = {}
self.__delayed_conf_timer = timers.timer(self.__delayed_config_send, 120)
self.__rate_limiter = rate_limit.RateLimiter(1000, 10000, 60) #maximum 1000 (in average) flows per 60 seconds (peak 10000)
self.__rate_limiter = rate_limit.RateLimiter(int(self.__config['rate_limit_number']), int(self.__config['rate_limit_interval']))
# A workaround. Currently, clients sometime need to recreate their local
# data structures, so they ask for configuration. However, the configuration ID
......
......@@ -18,25 +18,36 @@
#
import timers
import master_config
class RateLimiter():
"""
Rate Limiter (per client)
Implements token bucket for each client.
Parameters of buckets are:
- inflow (how many tokens will be added),
- interval (how often tokens will be added),
- capacity (maximum number of token).
Inflow and interval are specified when calling __init__, capacity is set in master configuration (rate_limiter_bucket_capacity).
The actual capacity (maximum number of tokens in buckets) is rate_limiter_bucket_capacity * inflow.
rate_limiter_bucket_capacity basically specifies the factor by which the normal limits might be exceeded.
Eg. with rate_limiter_bucket_capacity=5 clients might send 5 * the normal limits in a burst without being blocked (assuming their rate was below the normal limits before).
"""
def __init__(self, inflow, max_value, interval=None):
def __init__(self, inflow, interval=None):
"""
Initializes rate-limit (for all clients).
:param inflow: number of tokens added to bucket
:param max_value: max number of tokens in bucket
:param interval: number of second, every [interval] seconds [inflow] tokens are added to each client's bucket. If it's None, adding should be done manually.
Maximum number of tokens in the bucket is set to inflow * rate_limiter_bucket_capacity, which comes from master configuration.
"""
self.__buckets = {}
self.__inflow = inflow
self.__max_value = max_value
self.__max_value = inflow * master_config.getint('rate_limiter_bucket_capacity')
if interval:
timers.timer(self.add_tokens, interval, False)
......
......@@ -55,7 +55,7 @@ class RefusedPlugin(plugin.Plugin):
def __init__(self, plugins, config):
plugin.Plugin.__init__(self, plugins)
self.__config = config
self.__rate_limiter = rate_limit.RateLimiter(100, 1000, 60) #maximum 100 (in average) records per 60 seconds (peak 1000)
self.__rate_limiter = rate_limit.RateLimiter(int(self.__config['rate_limit_number']), int(self.__config['rate_limit_interval']))
def name(self):
return 'Refused'
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment