Skip to content

Rate limiter

devlibx edited this page Dec 11, 2022 · 21 revisions

This is a generic rate limiter, which uses Redis as a backend to provide distributed rate limit.


Here is an example of a configuration to set up a rate limiter.

enabled: true                                   # If true rate limiter is on otherwise, any call to rate limit will be no-op
rate_limiters:                                  # List of rate limits - you can define many rate limits which will have its own 
                                                # rate limit counter
  externalCallRateLimit:                        # name of rate limit - you will refer using this name in your code
    enabled: true                               # Enable this rate limiter or now
    redis:                                      # Redis details
      host: localhost
      port: 6379
      timeout: 3000                             # Following are Redis timeouts e.g. timeout, connection timeout etc
      connect_timeout: 10000
      idle_connection_timeout: 10000
      ping_connection_interval: 30000
    rate: 10                                    # What is the limit to apply (in per rate interval and rate interval unit)
    rate_interval: 1                            # Rate limit interval e.g. 1 sec, 1 min etc
    rate_interval_unit: SECONDS                 # Unit of rate limit interval time 

DynamoDB-specific rate limiter

We sometimes want to ensure, we do not go above WCU. We may have provisioned the DDB which will scale, but it takes time. And we want to adjust the rate limit to increase automatically. This lib gives a way to achieve most of it

  1. Automatically change the rate limit to match the WCU
  2. ALlow rate limiting to adjust so that the burst capacity (unused WCU during last 5 min can be utilized) This means, you may have only 100 WCU, but if they are not used then DDB will allow you to consume this in a burst. In this case rate limiter will adjust and will allow you to go ahead
  3. If anything goes wrong, the circuit will open and your code will not break. However, acquire call will be a no-op in this case.
    • maybe we can implement some kind of non-distributed rate limit as a fallback (TBD)
rate_limit_factory:
  enabled: true

  prefix: test_easy                      # This is important if you share the same Redis. This is to avoid namespace clash. Give 
                                         # different prefix to each service
                                         # all the data is stored with <prefix>-<some lib internal things>, and this prefix will avoid 
                                         # namespace collision 
  rate_limiters:
    example-config-normal:
      enabled: true

      redis:
        host: localhost
        port: 6379
        version: v3                      # v3 is where we have auto adjust rate limit. v1 is the basic rate limit which will only scale with 
                                         # WCU but will not adjust for burst and unused capacity    
      rate_type: OVERALL
      rate: 2
      rate_interval: 1                  # For the DDB use case, do not change it, it has to be 1 Sec. Not tested what will happen if this
                                        # is not the 1 sec 
      rate_interval_unit: SECONDS

      properties:
        enable-acquire-optimization: true    # This is an optimization to reduce the load in Redis. Try this if you see high CPU usage in 
                                             # redis  (recommended = set it to true)   

      rate_limit_job_config:
        refresh-time-in-sec: 10         # We need to check the actual DDB WCU value to adjust. This will tell how frequently we will do it                
        rate-limit-by-write: true
        rate-limit-class: io.github.devlibx.easy.ratelimit.job.ddb.DynamoDbWriteRateLimitJob

        rate-limit-factor: 1            # This is IMP. Suppose you have 100 WCU and you want the WCU to consume all then use 1. Suppose you 
                                        # want to leave some buffer e.g. even if I have 100 WCU never use > 90% capacity then you can 
                                        # adjust it by setting it 0.9
                                        # Simple logic - when I get the WCU from DDB, I just multiply that with this no and set it as the rate 
                                          limit
        region: ap-south-1
        enabled: true                 
        table: test                     # Your table name  

Things to ensure:

  1. You have Redis running at the boot (if Redis stops in between then we have circuit breakers to avoid the issue)
  2. You may see higher CPU usage in Redis
  3. MUST - you must have DDB table describing permission (only describe is sufficient)
Clone this wiki locally