DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Rate Limiting Strategies for Efficient Traffic Management
  • What Is the Difference Between API Rate Limiting and Throttle Controls?
  • Custom Rate Limiting for Microservices
  • Identify API Policies for All Levels in the Application Network With API-Led Connectivity

Trending

  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  • Microsoft Azure Synapse Analytics: Scaling Hurdles and Limitations
  • Mastering Fluent Bit: Installing and Configuring Fluent Bit on Kubernetes (Part 3)
  • What Is Plagiarism? How to Avoid It and Cite Sources
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Differentiating Rate Limits in Apache APISIX

Differentiating Rate Limits in Apache APISIX

Learn how to implement rate limiting with Apache APISIX: set the rate limit on a route, and move it to individual consumers and consumer groups.

By 
Nicolas Fränkel user avatar
Nicolas Fränkel
DZone Core CORE ·
Jul. 31, 24 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
2.8K Views

Join the DZone community and get the full member experience.

Join For Free

In my talk "Evolving your APIs," I mention that an API Gateway is a reverse proxy "on steroids." One key difference between the former and the latter is that the API Gateway is not unfriendly to business logic. The poster child is rate-limiting.

Rate-limiting is an age-old reverse proxy feature focused on protecting against DDoS attacks. It treats all clients the same and is purely technical. In this day and age, most API providers offer different subscription tiers; the higher the tier, the higher the rate limit, and the more you pay incidentally. It's not technical anymore and requires to differentiate between clients.

In this post, I want to detail how to do it with Apache APISIX. Note I take most of the material from the workshop.

Rate-Limiting for the Masses

Apache APISIX offers no less than three plugins to rate limit requests:

  • limit conn: Limits the number of concurrent requests
  • limit req: Limits the number of requests based on the Leaky Bucket algorithm
  • limit count: Limits the number of requests based on a fixed time window

The limit-count plugin is a good candidate for this post.

Let's configure the plugin for a route:

YAML
 
routes:
  - uri: /get
    upstream:
      nodes:
        "http://httpbin.org:80": 1
    plugins:
      limit-count:                     #1
        count: 1                       #2
        time_window: 60                #2
        rejected_code: 429             #3
#END


  1. Set the limit-count plugin.
  2. Limit requests to one every 60 seconds.
  3. Override the default HTTP response code, i.e., 503. 

At this point, we configured regular rate limiting.

Shell
 
curl -v http://localhost:9080/get
curl -v http://localhost:9080/get


If we execute the second request before a minute has passed, the result is the following:

HTTP
 
HTTP/1.1 429 Too Many Requests
Date: Tue, 09 Jul 2024 06:55:07 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 241
Connection: keep-alive
X-RateLimit-Limit: 1                   #1
X-RateLimit-Remaining: 0               #2
X-RateLimit-Reset: 59                  #3
Server: APISIX/3.9.1

<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>openresty</center>
<p><em>Powered by <a href="https://apisix.apache.org/">APISIX</a>.</em></p></body>
</html>


  1. Configured limit
  2. Remaining quota
  3. Waiting time in seconds before quota replenishment

Per-Consumer Rate Limiting

To configure per-consumer rate limiting, we first need to implement request authentication. APISIX offers many authentication plugins; we shall use the simplest one, key-auth. key-auth checks a specific HTTP request header - apikey by default.

Here's how we configure consumers:

YAML
 
consumers:
  - username: johndoe                  #1
    plugins:
      key-auth:
        key: john                      #2
  - username: janedoe                  #1
    plugins:
      key-auth:
        key: jane                      #2


  1. Users
  2. HTTP header request value
Shell
 
curl -H 'apikey: john' localhost:9080/get #1
curl -H 'apikey: jane' localhost:9080/get #2


  1. Authenticate as johndoe. 
  2. Authenticate as janedoe. 

In general, you attach plugins to APISIX routes but can also attach them to consumers. We can now move the limit-count plugin.

YAML
 
routes:
  - uri: /get
    upstream:
      nodes:
        "httpbin:80": 1
    plugins:
      key-auth: ~                      #1

consumers:
  - username: johndoe
    plugins:
      key-auth:
        key: john
      limit-count:
        count: 1                       #2
        time_window: 60
        rejected_code: 429
  - username: janedoe
    plugins:
      key-auth:
        key: jane
      limit-count:
        count: 5                       #2
        time_window: 60
        rejected_code: 429
#END


  1. The route is only accessible to requests authenticating with key-auth.
  2. johndoe has a lower limit count than janedoe. Did he forget to pay his subscription fees?
Shell
 
curl -H 'apikey: john' localhost:9080/get
curl -H 'apikey: john' localhost:9080/get
curl -H 'apikey: jane' localhost:9080/get
curl -H 'apikey: jane' localhost:9080/get


The second request gets rate-limited.

Per-Group Rate Limiting

We never attach permissions directly to identities in Identity Management systems. It's considered bad practice because when a person moves around the organization, we need to add and remove permissions one by one. The good practice is to attach permissions to groups and set the person in that group. When the person moves, we change their group; the person loses permissions from the old group and gets permissions from the new group. People get their permissions transitively via their groups.

Apache APISIX offers an abstraction called a Consumer Group for this.

Let's create two consumer groups with different rate limit values:

YAML
 
consumer_groups:
  - id: 1
    plugins:
      limit-count:
        count: 1
        time_window: 60
        rejected_code: 429
  - id: 2
    plugins:
      limit-count:
        count: 5
        time_window: 60
        rejected_code: 429


The next step is to attach consumers to these groups:

YAML
 
consumers:
  - username: johndoe
    group_id: 1
    plugins:
      key-auth:
        key: john
  - username: janedoe
    group_id: 2
    plugins:
      key-auth:
        key: jane


Shell
 
curl -H 'apikey: john' localhost:9080/get
curl -H 'apikey: john' localhost:9080/get
curl -H 'apikey: jane' localhost:9080/get
curl -H 'apikey: jane' localhost:9080/get


The second request gets rate-limited.

We have the same results as before with two benefits. The first one is as I wrote above: when consumers move in and out, they change their permissions accordingly.

The second benefit is that the limit count is shared among all consumers of a group. Indeed, when you set a limit, you don't want each consumer to be rate limited at X requests per Y second; you want the group as a whole to share the limit. In this way, if a single consumer is very active, they will naturally cap the rate of other consumers who share the same group.

Of course, you can set a limit on both a consumer and the group it belongs to. In this case, the lowest limit will apply first.

YAML
 
consumers:
  - username: johndoe
    group_id: 2                        #1  
    plugins:
      key-auth:
        key: john
      limit-count:
        count: 1                       #2
        time_window: 60
        rejected_code: 429
  - username: janedoe
    group_id: 2
    plugins:
      key-auth:
        key: jane


  1. Move johndoe to group 2.
  2. Limit him individually.
Shell
 
curl -H 'apikey: john' localhost:9080/get
curl -H 'apikey: john' localhost:9080/get #1


  1. johndoe hits the limit here, but janedoe now only has four requests left from this minute, as the former used one request.

Conclusion

In this post, we implement rate limiting with Apache APISIX. We set the rate limit on a route and moved it to individual consumers. Then we moved it to consumer groups, so all consumers in a group share the same "pool."

The complete source code for this post can be found on GitHub.

To Go Further

  • Consumer
  • Consumer Group
API consumer rate limit Requests

Published at DZone with permission of Nicolas Fränkel, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Rate Limiting Strategies for Efficient Traffic Management
  • What Is the Difference Between API Rate Limiting and Throttle Controls?
  • Custom Rate Limiting for Microservices
  • Identify API Policies for All Levels in the Application Network With API-Led Connectivity

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!