Strombegrenzeralgorithmus
Derzeit gibt es zwei gemeinsame Strombegrenzer -Algorithmen: Token -Bucket -Algorithmus und ein undichte Bucket -Algorithmus. Die Hauptdifferenz besteht darin, dass der undichte Bucket -Algorithmus die Anforderungsrate und die reibungslosen Burst -Anforderungen gewaltsam begrenzen kann, während der Token -Bucket -Algorithmus eine bestimmte Menge an Burst -Anforderungen ermöglicht, wenn die Durchschnittsrate eingeschränkt wird.
Im Folgenden finden Sie zwei Algorithmusdiagramme im Internet, die sich leicht von den Eigenschaften dieser beiden Algorithmen unterscheiden können.
Leck -Eimer -Algorithmus
Token -Bucket -Algorithmus
Für Schnittstellen dürfen eine bestimmte Anzahl von Burst -Anfragen im Allgemeinen verarbeitet werden, und es ist nur die Durchschnittsrate erforderlich, damit der Token -Bucket -Algorithmus häufiger ist.
Token -Bucket -Algorithmus -Tool -Ratelimiter
Der Token Bucket -Algorithmus -Implementierungsklasse I verwendet am häufigsten verwendete Ratelimiter von Google Guava. Guava implementiert nicht nur den Token -Bucket -Algorithmus, sondern auch den Cache, neue Sammlungsklassen, gleichzeitige Werkzeugklassen, String -Verarbeitungsklassen usw. Es ist ein leistungsstarkes Werkzeugsatz
Die Ratelimiter -API kann die Einführung des Guava -Ratelimiter im gleichzeitigen Programmiernetzwerk anzeigen
Analyse der Ratelimiter -Quellcode -Code
Standardmäßig sind die Kernattribute von Ratelimiter zwei NextFreeticketmicros. Die Token -Zeit kann beim nächsten Mal und die Anzahl der Token im Bahn der gespeicherten Zeiträume erhalten werden.
Bestimmen Sie, ob Sie das Token erhalten möchten:
Berechnen Sie jedes Mal, wenn Sie ein Token erhalten, die schnellste Zeit, um das Token beim nächsten Mal basierend auf der Anzahl der Token im Eimer zu bekommen. Wenn Sie feststellen, ob die Ressource erhalten werden kann, vergleichen Sie einfach NextFreeticketMicros mit der aktuellen Zeit.
Holen Sie sich Token -Operation:
Berechnen Sie für die Erlangung des Tokens die Anzahl der neuen Token basierend auf NextFreeticketmicros und der aktuellen Zeit, schreiben Sie die aktuelle Token -Bucket -Token -Nummer und neu in der nächsten Zeit. Wenn sich im Eimer ein Token befindet, schreiben Sie die aktuelle Zeit und reduzieren Sie die Anzahl der Token, die durch diese Anfrage erhalten wurden.
Genau wie die AQS -Klasse in Java ist der Kern von Ratelimiter die Tryacquire -Methode
public boolean tryacquire (int genehmigt, langfristig, Zeiteinheit) {// Versuche, die maximale Wartezeit lange ZeitoutMicros = max (Einheit.Tomicros (Zeitüberschreitung), 0) zu erhalten; // Überprüfen Sie, ob die Anzahl der erhaltenen Ressourcen korrekte CheckPerMits (Genehmigungen) ist. lange Mikrostowait; // Synchronisierte sperren (mutex ()) {// aktuelle Zeit lang nowmicros = stopwatch.readmicros (); // Beurteilen Sie, ob die Ressource innerhalb der Zeitüberschreitung erhalten werden kann, wenn (! Canacquire (nowmicros, timeoutmicros)) {return false; } else {// Die Ressource kann erhalten werden, die Ressource neu berechnet und die von dem aktuelle Thread Microstowait = ReserveAndGetwaitLength erforderliche Schlafzeit zurückgegeben werden (Genehmigungen, nowmicros); }} // Die Schlafstoppwatch.sleepmicrosuninterripticle (MicroStowait); zurückkehren; }Bestimmen Sie, ob Sie das Token erhalten möchten:
Private boolean Canacquire (lange NORMICROS, Langzeite -MICROS) {// Zu den frühesten Ressourcenzeiten kann erhalten werden - Wartezeit <= Die aktuelle Zeit kann erhalten werden, bevor die Ressource erhalten werden kann.Ratelimiter Standard -Implementierungsklassen QueryeArliestAbleable bestehen darin
Holen Sie sich das Token und berechnen Sie den erforderlichen Wartezeitvorgang:
endgültige lange ReserveandgetWaitLength (int Genehmigungen, lange NOWMICROS) {// Zeit, um das nächste Mal lang zu bekommen, langen Momentverfügbarkeit = ReserveAlliestAvailable (Genehmigungen, NOWMICROS); // Berechnen Sie die Schlafzeit für den aktuellen Thread, um max (momenta -Aperable - nowmicros, 0);}; endgültige lange, reservearlige Verfügbarkeit (int forforderedperMits, Long nowmicros) {// Die Anzahl der Token im Bucket StoredPerMits resync (nowmicros) neu berechnen; langes returnValue = nextFreeticketmicros; // die Anzahl der Token, die dieses Mal doppelt gelagert wurden, stand stermitstospend = min (erforderlicheMits, this.PoredPerMits); // Berechnen Sie die Zeit neu, um das nächste Mal als nächstes zu erhalten, doppelte FreshPerMits = forderePerMits - gespeichertePlemitstospend; long Waitmicros = gelagertPermitstowaittime (this.storedPerMits, gespeicherte Zeitpermitstospend) + (lang) (FreshPerMits * StableIntervalmicros); this.nextFreeticketmicros = longmath.saturatedAdd (NextFreeticketMicros, Waitmicros); // die Anzahl der Token im Eimer reduzieren. return returnValue; }Implementieren Sie einen einfachen Spring MVC -Stromlimit -Interceptor
Implementieren Sie einen Handlerinterzeptor, erstellen Sie einen Ratelimiter -Strombegrenzer im Konstruktor
public simimateatelimitInterceptor (int rate) {if (rate> 0) globalRatelimiter = ratelimiter.create (rate); sonst werfen Sie eine neue RunTimeException ("Rate muss größer als Null");}Rufen Sie die Tryacquire -Methode des aktuellen Begrenzer in Vorhandle an, um festzustellen, ob der Grenzrate ihn überschritten hat
public boolean prehandle (httpServletRequest -Anfrage, httpServletResponse -Antwort, Objekthandler) löst Ausnahme aus {if (! globalRatelimiter false zurückgeben; } Return true; }Konfigurieren Sie den aktuellen Grenzwert-Interceptor im Dispatcher-Service.xml
<MVC: Interceptors> <!-aktueller Grenzwert Interceptor-> <mvc: interceptor> <mvc: maping path = "/**"/> <bean> <constructor-arg Index = "0" value = "$ {TotalRate}"/> </bean> </mvc: interceptor> </mvc: interceptors> </mvc: interceptor> </mvc: interceptors>Komplexe Version von Spring MVC Current Limit Interceptor
Verwenden Sie die Eigenschaften, um den interceptierten URL -Expression zu übergeben -> Ratenrate
<mvc:interceptor> <mvc:mapping path="/**"/> <bean> <!--Single url current limit--> <property name="urlProperties"> <props> <prop key="/get/{id}">1</prop> <prop key="/post">2</prop> </props> </property> </bean></mvc:interceptor> Erstellen Sie für jeden URL -Expression einen entsprechenden Ratelimiterstrombegrenzer. Der URL -Ausdruck wird als org.springframework.web.servlet.mvc.condition.patternSrequestCondition eingekapselt. MustersRequestCondition ist eine Klasse, die in SpringMVCs DispatcherServlet verwendet wird, um Anforderungen und Controller zu entsprechen. Es kann bestimmen, ob die Anfrage diesen URL -Ausdrücken entspricht.
In der Interceptor Prehandle -Methode
// Der aktuelle Anforderungspfad -String -SOKUPPATH = urlpathHelper.getlookuppathForRequest (Anfrage); // Iterate über die MusterRequestCondition, die allen URL -Ausdrücken entspricht (mustersRequestConditions -MustersRequestCondition: urlratemap.Keyset ()) {// Machen Sie eine Match -Liste> Matches> patches <String> patches <string> patches = matchites <string> patches = matchites <string> patches = matchites <string -liste = String -liste <String <String <String> = String <String <String> -Intimation = String <String> -Liste = matchn. mustersRequestCondition.getMatchingPatterns (Lookuppath); if (! Matches.ISEMPTY ()) {// Wenn das Spiel erfolgreich ist, erhalten Sie das Token des entsprechenden aktuellen Limiters. Limiter "); } else {// versäumte es, den Token loggerutil.log zu erhalten (Lookuppath + "Anforderung überschreitet" + Joiner.on (","). Join (mustersRequestCondition.getPatterns ()) + "aktuelle Begrenzerrate"); false zurückgeben; }}}Spezifische Implementierungsklassen
Bitte siehe GitHub
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.