Heim  >  Artikel  >  Backend-Entwicklung  >  So begrenzen Sie den Fluss der API-Schnittstelle in PHP

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼Original
2019-09-27 15:30:217334Durchsuche

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

Was ist Schnittstellenstrombegrenzung?

Was ist also Strombegrenzung? Wie der Name schon sagt, dient die Strombegrenzung dazu, den Datenverkehr zu begrenzen, einschließlich des gleichzeitigen Datenverkehrs und des gesamten Datenverkehrs innerhalb eines bestimmten Zeitraums. Genauso wie Ihr Breitbandpaket 1 G Datenverkehr hat, wird dieser nach Verbrauch gelöscht. Kontrollieren Sie also Ihre Frequenz der Nutzung und des Gesamtverkehrs in einem einzigen Zeitraum. Durch die Strombegrenzung können wir die QPS des Systems gut steuern und so den Zweck erreichen, die Stabilität des Systems oder Schnittstellenservers zu schützen.

Häufig verwendete Algorithmen zur Schnittstellenstrombegrenzung

Zählermethode

Die Zählermethode ist die einfachste und einfachste unter den aktuellen begrenzende Algorithmen Ein implementierter Algorithmus. Beispielsweise legen wir fest, dass für die Schnittstelle A die Anzahl der Zugriffe pro Minute 100 nicht überschreiten darf. Dann können wir Folgendes tun: Zu Beginn können wir einen Zähler setzen. Immer wenn eine Anfrage kommt, wird der Zähler um 1 erhöht. Wenn der Wert des Zählers größer als 100 ist und das Intervall zwischen der Anfrage und der ersten Anfrage beträgt Noch innerhalb einer Minute bedeutet dies, dass zu viele Anfragen vorliegen. Wenn das Intervall zwischen der Anfrage und der ersten Anfrage größer als 1 Minute ist und der Wert des Zählers immer noch innerhalb des aktuellen Grenzbereichs liegt, wird der Zähler zurückgesetzt Der spezifische Algorithmus lautet wie folgt:

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

Der Pseudocode lautet wie folgt:

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;
        }
    }
}

Dieser Algorithmus sieht einfach aus, hat aber ein sehr ernstes Problem, nämlich das Kritikalitätsproblem. Siehe das Bild unten:

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

Wie wir aus dem Bild oben sehen können, nehmen wir an, dass es einen böswilligen Benutzer gibt, der um 0:59 Uhr sofort 100 Anfragen sendet erneut um 1:00 Uhr 100 Anfragen erhalten, dann hat dieser Benutzer tatsächlich 200 Anfragen in 1 Sekunde gesendet. Wir haben gerade ein Maximum von 100 Anfragen pro Minute festgelegt, was einem Maximum von 1,7 Anfragen pro Sekunde entspricht. Benutzer können unser Ratenlimit sofort überschreiten, indem sie Burst-Anfragen am Reset-Knoten des Zeitfensters stellen. Benutzer können diese Lücke im Algorithmus nutzen, um unsere Anwendung sofort zu überfordern.

Verwandte Empfehlungen: „php-Tutorial

Kluge Freunde haben vielleicht herausgefunden, dass das Problem gerade jetzt tatsächlich darin liegt, dass die Genauigkeit unserer Statistiken zu gering ist. Wie kann man also mit diesem Problem gut umgehen? Mit anderen Worten: Wie kann man die Auswirkungen kritischer Probleme reduzieren? Wir können uns den Schiebefensteralgorithmus unten ansehen.

Schiebefenster-Algorithmus

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

Im obigen Bild stellt das gesamte rote rechteckige Feld ein Zeitfenster dar, in unserem Beispiel ein Das Zeitfenster beträgt eine Minute. Dann unterteilen wir das Zeitfenster. In der Abbildung unterteilen wir beispielsweise das Schiebefenster in 6 Raster, sodass jedes Raster 10 Sekunden darstellt. Alle 10 Sekunden verschiebt sich unser Zeitfenster um einen Frame nach rechts. Jedes Raster verfügt über einen eigenen unabhängigen Zähler. Wenn beispielsweise eine Anfrage bei 0:35 Sekunden eintrifft, wird der entsprechende Zähler von 0:30 auf 0:39 um 1 erhöht.

Wie löst das Schiebefenster das gerade kritische Problem? Wir können uns das Bild oben ansehen. Die 100 um 0:59 Uhr eintreffenden Anfragen fallen in das graue Raster, während die um 1:00 Uhr eintreffenden Anfragen in das orangefarbene Raster fallen. Wenn die Zeit 1:00 erreicht, verschiebt sich unser Fenster um eine Stelle nach rechts. Dann beträgt die Gesamtzahl der Anforderungen im Zeitfenster zu diesem Zeitpunkt 200 und überschreitet den Grenzwert von 100, sodass erkannt werden kann, dass der aktuelle Grenzwert erreicht ist zu diesem Zeitpunkt ausgelöst.

Lassen Sie mich gerade den Zähleralgorithmus überprüfen. Wir können feststellen, dass der Zähleralgorithmus tatsächlich ein Schiebefensteralgorithmus ist. Es teilt das Zeitfenster nur nicht weiter auf, sodass es nur ein Raster gibt.

Es ist ersichtlich, dass das Gleiten des Schiebefensters gleichmäßiger verläuft und die aktuellen Begrenzungsstatistiken genauer sind, wenn das Schiebefenster in mehr Gitter unterteilt wird.

Leaky-Bucket-Algorithmus

Leaky-Bucket-Algorithmus, auch als Leaky-Bucket bekannt. Um den Leaky-Bucket-Algorithmus zu verstehen, werfen wir einen Blick auf das schematische Diagramm des Algorithmus auf Wikipedia:

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

Aus der Abbildung können wir ersehen, dass der gesamte Algorithmus tatsächlich vorhanden ist ganz einfach. Erstens haben wir einen Eimer mit festem Fassungsvermögen, in den Wasser ein- und ausgeht. Bei einströmendem Wasser können wir nicht vorhersagen, wie viel Wasser einströmen wird und auch nicht, wie schnell das Wasser fließen wird. Aber für das ausfließende Wasser kann dieser Eimer die Geschwindigkeit festlegen, mit der das Wasser ausfließt. Außerdem läuft das überschüssige Wasser über, wenn der Eimer voll ist.

Wir ersetzen das Wasser im Algorithmus durch Anfragen in tatsächlichen Anwendungen. Wir können sehen, dass der Leaky-Bucket-Algorithmus die Geschwindigkeit von Anfragen grundsätzlich begrenzt. Durch die Verwendung des Leaky-Bucket-Algorithmus können wir sicherstellen, dass die Schnittstelle Anfragen mit einer konstanten Geschwindigkeit verarbeitet. Daher weist der Leaky-Bucket-Algorithmus von Natur aus keine Kritikalitätsprobleme auf. Die spezifische Pseudocode-Implementierung lautet wie folgt:

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;
        }
    }
}

Token-Bucket-Algorithmus

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

So begrenzen Sie den Fluss der API-Schnittstelle in 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后才能发生。

So begrenzen Sie den Fluss der API-Schnittstelle in PHP

总结

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

漏桶算法 VS 令牌桶算法

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

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

Das obige ist der detaillierte Inhalt vonSo begrenzen Sie den Fluss der API-Schnittstelle in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn