ratelimit icon indicating copy to clipboard operation
ratelimit copied to clipboard

Way to create different time units?

Open vincentjames501 opened this issue 5 years ago • 22 comments

We'd like to implement rate limiting such that certain time-periods have time have different limits (i.e. bursting). For example:

Scenario Time-period (sec) Max allowed operations
Send to Conversation 1 5
Send to Conversation 30 60
Send to Conversation 300 100

Right now the configuration is pretty simple with:

rate_limit:
  unit: <second, minute, hour, day>
  requests_per_unit: <uint>

The problem is that I can't adjust the unit to be something like 30 seconds or 5 minutes (or at least I'm not clear how one would set that).

What would folks think about adding some unit multiplier such as:

rate_limit:
  unit_multiplier: <uint | default=1>
  unit: <second, minute, hour, day>
  requests_per_unit: <uint>

This would allow someone to easily express 30 seconds or 5 minutes?

vincentjames501 avatar Nov 13 '20 17:11 vincentjames501

It also appears I can only get one rate limit to match and be processed. Is there a way to have multiple rate limits be applied to a single route?

                      routes:
                        - match:
                            prefix: /api/
                            headers: 
                              name: :method
                              exact_match: GET
                          route:
                            cluster: api
                            rate_limits:
                              - actions:
                                  - request_headers:
                                      header_name: x-user-id
                                      descriptor_key: default_get_limit_sm
                                  - request_headers:
                                      header_name: x-user-id
                                      descriptor_key: default_get_limit_med
                                  - request_headers:
                                      header_name: x-user-id
                                      descriptor_key: default_get_limit_lg
---
domain: rl
descriptors:
  - key: default_get_limit_sm
    rate_limit:
      unit: second
      requests_per_unit: 30
  - key: default_get_limit_md
    rate_limit:
      unit: minute
      requests_per_unit: 120
  - key: default_get_limit_lg
    rate_limit:
      unit: hour
      requests_per_unit: 1800

It could be neat if instead of rate_limit there was rate_limits which would be an array of rate_limit objects?

vincentjames501 avatar Nov 13 '20 17:11 vincentjames501

I figured out the multiple rate limits for a given route. I'll post that here incase anyone else runs into the same thing.

                    routes:
                        - match:
                            prefix: /api/
                            headers: 
                              name: :method
                              exact_match: GET
                          route:
                            cluster: api
                            rate_limits:
                              - actions:
                                - generic_key: 
                                    descriptor_value: default_get_sm
                                - request_headers:
                                    header_name: x-user-id
                                    descriptor_key: user_id
                              - actions:
                                  - generic_key: 
                                      descriptor_value: default_get_md
                                  - request_headers:
                                      header_name: x-user-id
                                      descriptor_key: user_id
                              - actions:
                                  - generic_key: 
                                      descriptor_value: default_get_lg
                                  - request_headers:
                                      header_name: x-user-id
                                      descriptor_key: user_id
---
domain: rl
descriptors:
  - key: generic_key
    value: default_get_sm
    descriptors:
      - key: user_id
        rate_limit:
          unit: second
          requests_per_unit: 30
  - key: generic_key
    value: default_get_md
    descriptors:
      - key: user_id
        rate_limit:
          unit: minute
          requests_per_unit: 120
  - key: generic_key
    value: default_get_lg
    descriptors:
      - key: user_id
        rate_limit:
          unit: hour
          requests_per_unit: 1800

vincentjames501 avatar Nov 13 '20 18:11 vincentjames501

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

stale[bot] avatar Dec 19 '20 08:12 stale[bot]

We would also benefit from "bursting" where, eg. 30r/3s would support a burst of 30 requests with a sustained traffic of 10 requests/s.

I don't believe there's any option for that today.

cesutherland avatar Jan 13 '21 20:01 cesutherland

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or "no stalebot" or other activity occurs. Thank you for your contributions.

github-actions[bot] avatar Feb 13 '21 00:02 github-actions[bot]

Can this be tagged with help wanted at least?

vincentjames501 avatar Feb 13 '21 01:02 vincentjames501

Sorry what is the actual request? I think we support multiple limits today. Can bursting be expressed as multiple concurrent rate limits?

mattklein123 avatar Feb 14 '21 19:02 mattklein123

@mattklein123 Yes, this service can represent multiple rate limits for bursting today. The issue is our company has different time windows they want to enforce limits on that don't fit into second, minute, hour, and day units. For example, you can't really make these limits:

X requests over 30 seconds
X requests over 5 minutes
X requests over 30 minutes
X requests over 12 hours
X requests over 7 days

The proposal I made earlier was some sort of unit multiplier such as:

rate_limit:
  unit_multiplier: <uint | default=1>
  unit: <second, minute, hour, day>
  requests_per_unit: <uint>

which would allow you to represent any time period. Does that make sense?

vincentjames501 avatar Feb 14 '21 20:02 vincentjames501

which would allow you to represent any time period. Does that make sense?

Yup OK makes sense. I will mark it help wanted.

mattklein123 avatar Feb 14 '21 20:02 mattklein123

I would also like to set multiple units for a single action so:

            descriptors:
              - key: remote_address
                rate_limit:
                  unit: second
                  requests_per_unit: 3
                rate_limit:
                  unit: day
                  requests_per_unit: 100

That is currently (afaik) not possible without duplicating the complete action with a generic key.

MischaWeerwag avatar Jul 28 '21 15:07 MischaWeerwag

This seems like a very nice feature as just converting your bucket to a 1 second or 1 minute bucket can be undesirable. Since with larger time units you can catch bursts more easily, but the user has to wait longer before reaching the new bucket.

rate_limit:
  unit_multiplier: <uint | default=1>
  unit: <second, minute, hour, day>
  requests_per_unit: <uint>

In my case something like a 10 second bucket would be perfect.

basimons avatar Oct 11 '22 15:10 basimons

Hi.

I can work on this improvement if you don't mind

uzzz avatar May 25 '23 13:05 uzzz

I think this feature is extremely important. You can develop it and create PR. I can fork that PR to test for you. Because we really need it right now. Tks you

quyenhoang96 avatar Jun 21 '23 04:06 quyenhoang96

@uzzz @quyenhoang96 did you got any progress on this feature? how could I support you to get this done?

eduardosanzb avatar Aug 03 '23 17:08 eduardosanzb

I would also like to set multiple units for a single action so:

            descriptors:
              - key: remote_address
                rate_limit:
                  unit: second
                  requests_per_unit: 3
                rate_limit:
                  unit: day
                  requests_per_unit: 100

That is currently (afaik) not possible without duplicating the complete action with a generic key.

@MischaWeerwag how did you achieved this? do you have an example?

eduardosanzb avatar Aug 03 '23 17:08 eduardosanzb

We would also like to see something like this, has there been any work on this?

harpunius avatar Jan 18 '24 11:01 harpunius

Any update on this?

vamsibandarupalli avatar Mar 19 '24 15:03 vamsibandarupalli