Maison  >  Article  >  développement back-end  >  Comment limiter le flux de l'interface API en php

Comment limiter le flux de l'interface API en php

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼original
2019-09-27 15:30:217329parcourir

Comment limiter le flux de l'interface API en php

Qu'est-ce que la limitation de courant d'interface ?

Alors, qu'est-ce que la limitation de courant ? Comme son nom l'indique, la limitation actuelle consiste à limiter le trafic, y compris le trafic simultané et le trafic total sur une certaine période de temps. Tout comme votre forfait haut débit contient 1 Go de trafic, il disparaîtra une fois épuisé, alors contrôlez votre fréquence. d'utilisation et le trafic total en une seule fois. Grâce à la limitation de courant, nous pouvons bien contrôler le qps du système, atteignant ainsi l'objectif de protéger la stabilité du système ou du serveur d'interface.

Algorithmes couramment utilisés pour la limitation du courant d'interface

Méthode du compteur

La méthode du compteur est la plus simple et la plus facile parmi les méthodes actuelles algorithmes limitants Un algorithme implémenté. Par exemple, on précise que pour l'interface A, le nombre d'accès en une minute ne peut excéder 100. Ensuite, nous pouvons faire ceci : au début, nous pouvons définir un compteur. Chaque fois qu'une requête arrive, le compteur sera augmenté de 1. Si la valeur du compteur est supérieure à 100 et que l'intervalle entre la requête et la première requête est égal à 1. toujours dans 1 minute, cela signifie qu'il y a trop de requêtes ; si l'intervalle entre la requête et la première requête est supérieur à 1 minute et que la valeur du compteur est toujours dans la plage limite actuelle, réinitialisez le compteur. de l'algorithme spécifique est le suivant :

Comment limiter le flux de linterface API en php

Le pseudo code est le suivant :

class CounterDemo{
    private  $timeStamp;
    public  $reqCount=0;
    public  $limit=100;//时间窗口内最大请求数
    public $interval=1000; //时间窗口 ms
    public function __construct()
    {
        $this->timeStamp = time();
    }
    public  function grant(){
        $now=time();
        if($now<$this->timeStamp+$this->interval){
            //时间窗口内
            $this->reqCount++;
            return $this->reqCount<=$this->limit;
        }else{
            // 超时后重置
            $this->timeStamp=time();
            $this->reqCount=1;
            return true;
        }
    }
}

Cet algorithme a l'air simple mais a un problème très sérieux, qui est le problème de criticité. Voir l'image ci-dessous :

Comment limiter le flux de linterface API en php

Comme nous pouvons le voir sur l'image ci-dessus, supposons qu'il y ait un utilisateur malveillant qui envoie instantanément 100 requêtes à 0h59, et encore une fois à 1h00, j'ai reçu 100 requêtes, alors en fait, cet utilisateur a envoyé 200 requêtes instantanément en 1 seconde. Ce que nous venons de définir est un maximum de 100 requêtes par minute, soit un maximum de 1,7 requêtes par seconde. Les utilisateurs peuvent dépasser notre limite de débit instantanément en effectuant des requêtes en rafale au nœud de réinitialisation de la fenêtre horaire. Les utilisateurs peuvent utiliser cette faille dans l'algorithme pour submerger instantanément notre application.

Recommandations associées : "Tutoriel php"

Des amis intelligents ont peut-être compris que le problème à l'instant est en fait dû au fait que la précision de nos statistiques est trop faible. Alors, comment bien gérer ce problème ? En d’autres termes, comment réduire l’impact des problèmes critiques ? Nous pouvons examiner l'algorithme de fenêtre glissante ci-dessous.

Algorithme de fenêtre coulissante

Comment limiter le flux de linterface API en php

Dans l'image ci-dessus, l'intégralité de la boîte rectangulaire rouge représente une fenêtre temporelle, dans notre exemple, une la fenêtre de temps est d’une minute. Ensuite, nous divisons la fenêtre temporelle. Par exemple, sur la figure, nous divisons la fenêtre glissante en 6 grilles, chaque grille représente donc 10 secondes. Toutes les 10 secondes, notre fenêtre temporelle glissera d’une image vers la droite. Chaque grille possède son propre compteur indépendant. Par exemple, lorsqu'une requête arrive à 0:35 secondes, le compteur correspondant de 0:30 à 0:39 sera incrémenté de 1.

Alors, comment la fenêtre coulissante résout-elle le problème critique du moment ? On peut regarder l'image ci-dessus. Les 100 requêtes arrivant à 0h59 tomberont dans la grille grise, tandis que les requêtes arrivant à 1h00 tomberont dans la grille orange. Lorsque l'heure atteint 1h00, notre fenêtre se déplacera d'un espace vers la droite. Ensuite, le nombre total de requêtes dans la fenêtre horaire à ce moment est de 200, dépassant la limite de 100, on peut donc détecter que la limite actuelle est. déclenché à ce moment.

Permettez-moi de passer en revue l'algorithme du compteur tout à l'heure. Nous pouvons constater que l'algorithme du compteur est en fait un algorithme à fenêtre glissante. C'est juste que cela ne divise pas davantage la fenêtre horaire, il n'y a donc qu'une seule grille.

On peut voir que lorsque la fenêtre glissante est divisée en plusieurs grilles, le déroulement de la fenêtre coulissante sera plus fluide et les statistiques de limitation actuelles seront plus précises.

Algorithme de seau qui fuit

Algorithme de seau qui fuit, également connu sous le nom de seau qui fuit. Afin de comprendre l'algorithme du seau qui fuit, jetons un coup d'œil au diagramme schématique de l'algorithme sur Wikipédia :

Comment limiter le flux de linterface API en php

D'après la figure, nous pouvons voir que l'ensemble de l'algorithme est en fait très simple. Premièrement, nous avons un seau d’une capacité fixe, avec de l’eau qui entre et de l’eau qui sort. Pour l’eau qui entre, nous ne pouvons pas prédire la quantité d’eau qui entrera, ni la vitesse à laquelle elle s’écoulera. Mais pour l’eau qui s’écoule, ce seau peut fixer la vitesse à laquelle l’eau s’écoule. De plus, lorsque le seau est plein, l’excès d’eau déborde.

Nous remplaçons l'eau dans l'algorithme par des requêtes dans des applications réelles. Nous pouvons voir que l'algorithme du seau qui fuit limite intrinsèquement la vitesse des requêtes. En utilisant l’algorithme du bucket qui fuit, nous pouvons garantir que l’interface traitera les demandes à un rythme constant. Par conséquent, l’algorithme du seau à fuite ne pose pas, en soi, de problèmes de criticité. L'implémentation spécifique du pseudocode est la suivante :

class LeakyDemo{
    private  $timeStamp;
    public  $capacity;// 桶的容量
    public  $rate; // 水漏出的速度
    public  $water;// 当前水量(当前累积请求数)
    public function __construct()
    {
        $this->timeStamp = time();
    }
    public  function grant(){
        $now=time();
        $this->water=max(0,$this->water-($now-$this->timeStamp)*$this->rate);// 先执行漏水,计算剩余水量
        $this->timeStamp=$now;
        if(($this->water+1)<$this->capacity){
            // 尝试加水,并且水还未满
            $this->water+=1;
            return true;
        }else{
            // 水满,拒绝加水
            return false;
        }
    }
}

Algorithme de seau de jetons

令牌桶算法,又称token bucket。为了理解该算法,我们再来看一下维基百科上对该算法的示意图:

Comment limiter le flux de linterface API en php

从图中我们可以看到,令牌桶算法比漏桶算法稍显复杂。首先,我们有一个固定容量的桶,桶里存放着令牌(token)。桶一开始是空的,token以一个固定的速率r往桶里填充,直到达到桶的容量,多余的令牌将会被丢弃。每当一个请求过来时,就会尝试从桶里移除一个令牌,如果没有令牌的话,请求无法通过。

具体的伪代码实现如下:

class TokenBucketDemo{
    private  $timeStamp;
    public  $capacity;// 桶的容量
    public  $rate; // 令牌放入的速度
    public  $tokens;// 当前令牌的数量
    public function __construct()
    {
        $this->timeStamp = time();
    }
    public  function grant(){
        $now=time();
        $this->tokens=min(0,$this->tokens+($now-$this->timeStamp)*$this->rate);// 先执行漏水,计算剩余水量
        $this->timeStamp=$now;
        if($this->tokens<1){
            // 若不到1个令牌,则拒绝
            return false;
        }else{
            // 还有令牌,领取令牌
            $this->tokens -= 1;
            return true;
        }
    }
}

临界问题

我们再来考虑一下临界问题的场景。在0:59秒的时候,由于桶内积满了100个token,所以这100个请求可以瞬间通过。但是由于token是以较低的 速率填充的,所以在1:00的时候,桶内的token数量不可能达到100个,那么此时不可能再有100个请求通过。所以令牌桶算法可以很好地解决临界问题。下图比较了计数器(左)和令牌桶算法(右)在临界点的速率变化。我们可以看到虽然令牌桶算法允许突发速率,但是下一个突发速率必须要等桶内有足够的token后才能发生。

Comment limiter le flux de linterface API en php

总结

计数器算法是最简单的算法,可以看成是滑动窗口的低精度实现。滑动窗口由于需要存储多份的计数器(每一个格子存一份),所以滑动窗口在实现上需要更多的存储空间。也就是说,如果滑动窗口的精度越高,需要的存储空间就越大。

漏桶算法 VS 令牌桶算法

漏桶算法和令牌桶算法最明显的区别是令牌桶算法允许流量一定程度的突发。因为默认的令牌桶算法,取走token是不需要耗费时间的,也就是说,假设桶内有100个token时,那么可以瞬间允许100个请求通过。

令牌桶算法由于实现简单,且允许某些流量的突发,对用户友好,所以被业界采用地较多。当然我们需要具体情况具体分析,只有最合适的算法,没有最优的算法。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn