web-dev-qa-db-fra.com

Comment limiter la vitesse d'une API

Quelle est la meilleure façon de limiter les demandes d'une API? Fondamentalement, nous voulons limiter les utilisateurs à 360 demandes d'API par heure (une demande toutes les 10 secondes). Ce qui me vient à l'esprit est le suivi de chaque demande d'API et le stockage:

  ip-address          hourly-requests
  1.2.3.4             77
  2.3.4.5             34
  3.4.5.6             124

Si les demandes d'adresse IP sont supérieures à 360, renvoyez simplement un en-tête avec:

  429 - Too Many Requests

Ensuite, annulez le compteur toutes les heures. Cela semble être une méthode très inefficace, car nous devons effectuer une requête MySQL sur chaque demande d'API pour incrémenter le compteur. De plus, nous aurions besoin d'une tâche cron pour réinitialiser tous les compteurs toutes les heures.

Existe-t-il une solution plus élégante/efficace?

55
Justin

Vous pouvez essayer d'utiliser Redis, il existe peu de modèles de limitation de débit

30
Alehandro Sanchez

Je ne recommanderais certainement pas de le faire avec MySQL - le problème n'est pas tant la lecture ou l'inefficacité de l'algorithme que vous mettez en évidence - mais écrit. Au fur et à mesure que les volumes augmentent, vous commencez à effectuer des écritures de plusieurs secondes. Nous utilisons REDIS comme stockage comme une autre affiche déjà mentionnée - elle a des fonctions d'incrémentation/décrémentation atomiques qui sont exactement ce dont vous avez besoin + c'est extrêmement rapide (en mémoire) - il vous suffit de gérer le partage à des volumes ultra élevés (mais cet ultra-haut est plusieurs ordres de grandeur au-dessus de MySQL). Une autre option si vous n'êtes pas familier avec REDIS est en train de le faire dans Memcached - mais ce n'est pas tout à fait aussi agréable au niveau des opérations.

Une autre option est toujours d'utiliser quelque chose comme 3scale (http://www.3scale.net) qui fait effectivement tout cela pour vous + d'autres choses (analytique, gestion des clés, documentation pour les développeurs, etc.). Il existe des plugins de code pour tout un tas de langues (https://support.3scale.net/libraries) et ceux-ci se connectent à l'infrastructure. Vous pouvez également utiliser le Varnish Libmod (https://github.com/3scale/libvmod-3scale/) et le brancher dans un cache Varnish en face de l'API.

11
steve

Essayez nginx. La limitation de débit peut être effectuée facilement en écrivant de simples modifications dans le fichier de configuration. De plus, nginx est rapide.

11
Kartik Goyal

Pour une quantité idéale de performances, vous pouvez exécuter un framework Web léger avec des fonctions de gestion des journaux sur une base de données en mémoire pour surveiller et enregistrer les données de trafic, que ce soit basé sur [~ # ~] ip [~ # ~] ou Utilisateur ou Service appelé par l'utilisateur . Le choix le plus important est le stockage de données que vous souhaitez utiliser.

Les options gratuites les meilleures et les plus utilisées sont:

redis.io magasin de valeurs-clés avancé

ehcache cache basé sur les normes, activement développé, maintenu et pris en charge en tant que projet open source professionnel par Terracotta

Hazelcast une grille de données en mémoire open source pour une exécution plus rapide et une évolutivité élastique transparente

VoltDB une base de données opérationnelle en mémoire

6
kommradHomer

J'étudie actuellement ce problème également. Mon plan actuel (notez que c'est avec une pile LAMP!) Est de l'implémenter en utilisant les fonctions de mise en cache d'APC. Lorsqu'une demande est reçue, je vérifie si cette IP est stockée dans le cache d'APC. Si tel est le cas, vérifiez s'il est supérieur à "X", où "X" correspond au nombre maximal de demandes par unité de temps. Si ce n'est pas le cas, créez l'entrée de cache pour cette IP.

Ce système signifie qu'aucun accès à la base de données n'est requis pour vérifier la limitation de débit, et il ne repose sur rien comme un serveur MongoDB ou Redis. Il suppose que vous utilisez PHP avec APC; si vous ne l'êtes pas, alors memcached pourrait fonctionner à la place.

2
Mechcozmo