API throttling et rate limiting


Nous allons aujourd’hui aborder 2 concepts : l’API throttling et le rate limiting.

Le premier sert à protéger d’un trop grand nombre de requêtes simultanées sur une API REST par exemple, ou tout serveur HTTP et même cluster de serveurs HTTP (au niveau du load balancer).

Le deuxième sert à s’auto-limiter en se fixant un nombre maximum d’actions par période donnée.
Cela peut être un nombre d’octets par seconde pour limiter l’usage de bande passante ou bien un nombre de requêtes par minute vers un référentiel commun au SI qui n’a pas lui même une protection avec une gestion de quota par exemple.

API throttling

 

Côté serveur

Dans la conception d’une API REST, il est bien dans les tests de charge de mesurer la limite du nombre de requêtes simultanées que peut accepter la plateforme et de mettre en place un système empêchant de dépasser cette limite pour ne pas dégrader le fonctionnement pour l’ensemble des utilisateurs.

L’exemple classique est l’application mobile qui suite à un coup de pub reçoit un succès non prévu.
Si rien n’est fait, les utilisateurs vont constater des dysfonctionnements tels qu’ils risquent de ne plus revenir.
Des dysfonctionnements du genre login particulièrement long (plus d’une minute), double débit sur la carte bleue lors d’un paiement, etc…
Le plus sage est de mettre en place un système qui va répondre un code d’erreur HTTP lors du dépassement de la limite.
Le code HTTP prévu pour ça est le code 429 Too many requests.

HTTP 429 Too Many Requests

Cette erreur est prévue dans la RFC 6585 Additional HTTP Status Codes.

Petit extrait :

The 429 status code indicates that the user has sent too many requests in a given amount of time (« rate limiting »).

The response representations SHOULD include details explaining the condition, and MAY include a Retry-After header indicating how long to wait before making a new request…

Note that this specification does not define how the origin server identifies the user, nor how it counts requests. For example, an origin server that is limiting request rates can do so based upon counts of requests on a per-resource basis, across the entire server, or even among a set of servers. Likewise, it might identify the user by its authentication credentials, or a stateful cookie.

Responses with the 429 status code MUST NOT be stored by a cache…

Il y a différentes façons d’implémenter une limitation.
Le plus simple est le paramétrage du load balancer s’il dispose de cette fonctionnalité.
Par exemple pour HAProxyhttps://blog.codecentric.de/en/201n4/12/haproxy-http-header-rate-limiting/

On peut aussi le faire au niveau des serveurs HTTP Apache frontaux avec un module. Il en existe des tout faits, mais on peut aussi en développer un custom sur mesure qui à l’aide d’un serveur memcached (ou Redis…) va centraliser pour l’ensemble des serveurs Apache les données d’usage par utilisateur, IP ou tout autre identifiant qui peut être géré par cookie par exemple.

L’intérêt d’un module sur mesure est de permettre de gérer l’ensemble des règles de limitation qui peuvent exister.
Par exemple :

  • Limitation globale basée sur le temps : 10000 requêtes par seconde
  • Limitation pour un service en particulier : 100 appel du POST /ressource/client par seconde
  • Limitation pour une catégorie ou une liste d’utilisateurs : limitations différentes pour les utilisateurs non authentifiés
  • Combinaison des 3
  • Limitation par seconde / minute / heure / jour / semaine / mois / année : 1 requête par seconde
  • Combinaison : maximum 1 requête par seconde et 10000 par mois
  • Limitation basée sur le volume : 10Mo en upload ou en download par heure
  • Limitation en nombre de réponse : 200 résultats max par requête et 5000 résultats par jour

Certaines limitations servent plus à limiter l’usage pour éviter les abus qu’à protéger les serveurs de la surcharge.
Ca peut aussi permettre de mettre en place une facturation par pallier.

Côté client

Du côté du client, par exemple dans une application mobile qui appelle des services REST, il faut gérer le code HTTP 429 comme une demande d’attendre avant de retenter la requête.
Le code HTTP 429 peut être accompagné par le header Retry-After indiquant le temps d’attente suggéré.
L’application doit également gérer un nombre de tentatives maximum afin de rendre la main ou bien afficher un message d’erreur à l’utilisateur ou bien passer en mode dégradé ou offline / asynchrone.

 

Rate limiting

Le rate limiting, c’est un peu dans l’autre sens, l’auto-limitation de l’usage d’une ressource ou bien d’une bande passante.
Par exemple, pour un batch devant tourner en pleine journée, on va pouvoir limiter son rythme de requêtage à une API pour laisser la priorité aux vrais utilisateurs.

En Java, la librairie Google Guava offre la classe RateLimiter pour implémenter une limite par seconde : http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/RateLimiter.html

Laissez un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *