Implement user based throttling with WSO2 API Manager
WSO2 API Manager throttling implementation is done in a manner so that API designers have the full flexibility to throttle API consumers at all levels. It supports throttling at
- API level
- Resource level
- Application level
- Subscription level
- Oauth2 token level
with out of the box throttling tiers and configurations. Users can manage throttling at above mentioned levels using the OOTB functionalities available in the product. The below 2 figures explains how the throttling is applicable across different levels and how they are executed during the runtime.
The different throttling levels which are configured from the API manager will apply during the runtime as depicted in the below figure.
In this article, I’m going to discuss how to implement custom throttling rules to throttle API requests based on users. To do this, users needs to log in to the admin interface of the WSO2 API manager runtime which is deployed in the following URL.
Once you log in, you can go to the Throttling Policies tab and navigate to Custom rules section where you can add a new custom rule. These custom rules needs to be implemented in Siddhi query language which is somewhat similar to SQL per say. The below section is extracted from the WSO2 API Manager documentation.
Custom throttling allows system administrators to define dynamic rules for specific use cases, which are applied globally across all tenants. When a custom throttling policy is created, it is possible to define any policy you like. The Traffic Manager acts as the global throttling engine and is based on the same technology as WSO2 Complex Event Processor (CEP), which uses the Siddhi query language. Users are therefore able to create their own custom throttling policies by writing custom Siddhi queries. The specific combination of attributes being checked in the policy need to be defined as the key (also called the key template). The key template usually includes a predefined format and a set of predefined parameters. It can contain a combination of allowed keys separated by a colon (:), where each key must start with the prefix $. The following keys can be used to create custom throttling policies:
resourceKey, userId, apiContext, apiVersion, appTenant, apiTenant, appId
Let’s write a custom policy to restrict any user from sending more than 5 requests to all the APIs running on the gateway.
FROM RequestStream
SELECT userId, userId as throttleKey
INSERT INTO EligibilityStream;
FROM EligibilityStream#throttler:timeBatch(1 min)
SELECT throttleKey, (count(userId) >= 5) as isThrottled, expiryTimeStamp group by throttleKey
INSERT ALL EVENTS into ResultStream;
In the above script, we select the userId as throttleKey and check the number of requests received to the gateway within a time span of 1 minute and make it throttled if the request count is greater than or equal to 5.
Let’s write another script to restrict only a given user (“admin”) with a limit of 5 requests per minute.
FROM RequestStream
SELECT userId, ( userId == ‘admin@carbon.super’ ) AS isEligible , str:concat(‘admin@carbon.super’,’’) as throttleKey
INSERT INTO EligibilityStream;
FROM EligibilityStream[isEligible==true]#throttler:timeBatch(1 min)
SELECT throttleKey, (count(userId) >= 5) as isThrottled, expiryTimeStamp group by throttleKey
INSERT ALL EVENTS into ResultStream;
In the above script, we check the username to be “admin” and then apply the throttling limit.
If we want to restrict all the users other than “admin” from sending more than 5 requests per minute, we can implement it like below.
FROM RequestStream
SELECT userId, ( userId != ‘admin@carbon.super’ ) AS isEligible, userId as throttleKey
INSERT INTO EligibilityStream;
FROM EligibilityStream[isEligible==true]#throttler:timeBatch(1 min)
SELECT throttleKey, (count(userId) >= 5) as isThrottled, expiryTimeStamp group by throttleKey
INSERT ALL EVENTS into ResultStream;
Above script will block all the users other than “admin” user from sending more than 5 requests per minute.
Happy throttling with WSO2 API Manager !