Algorithme de limiteur de courant
Actuellement, il existe deux algorithmes de limiteur de courant commun: l'algorithme de godet de jeton et l'algorithme de godet qui fuit. La principale différence est que l'algorithme de godet qui fuit peut limiter de force le taux de demande et les demandes de rafale en douceur, tandis que l'algorithme de godet de jeton permet une certaine quantité de demandes d'éclatement lors de la limitation du taux moyen.
Vous trouverez ci-dessous deux diagrammes d'algorithmes trouvés sur Internet, qui peuvent être facilement distingués des caractéristiques de ces deux algorithmes.
Algorithme de seau de fuite
Algorithme de seau de jeton
Pour les interfaces, un certain nombre de demandes de rafale sont généralement autorisées à être traitées, et seul le taux moyen est nécessaire pour limiter, de sorte que l'algorithme de godet de jeton est plus courant.
Outil d'algorithme de godet de jeton Ratelimiter
L'algorithme d'algorithme de token de la classe que je utilise le plus couramment utilisé est le Ratelimiter de Google Guava. La goyave implémente non seulement l'algorithme de godet de jeton, mais aussi le cache, les nouvelles classes de collection, les classes d'outils simultanées, les classes de traitement des chaînes, etc. Il s'agit d'un ensemble d'outils puissant
L'API Ratelimiter peut voir l'introduction de Guava Ratelimiter dans le réseau de programmation simultanée
Analyse du code source Ratelimiter
Par défaut, les attributs les plus principaux de Ratelimiter sont deux NextFreeTticketMicros. Le temps de jeton peut être obtenu la prochaine fois et le nombre de jetons dans le seau stocké.
Déterminez s'il faut obtenir le jeton:
Chaque fois que vous obtenez un jeton, calculez le meilleur temps pour obtenir le jeton la prochaine fois en fonction du nombre de jetons dans le seau. Lorsque vous déterminez si la ressource peut être obtenue, comparez simplement NextFreeTticketMicros avec l'heure actuelle.
Obtenez une opération de jeton:
Pour obtenir le jeton, calculez le nombre de nouveaux jetons basés sur NextFreeTticketMicros et l'heure actuelle, écrivez le numéro de jeton de jeton actuel et recalculez NextFreeTticketMicros. S'il y a un jeton dans le seau, écrivez l'heure actuelle et réduisez le nombre de jetons obtenus par cette demande.
Tout comme la classe AQS en Java, le cœur de Ratelimiter est la méthode Tryacquire
Boolean Public TryAcquire (INT PERMITS, Long Timeout, TimeUnit Unit) {// Essayez d'obtenir le temps d'attente maximum Long TimeoutMicros = Max (unit.tomicros (temps mort), 0); // Vérifiez si le nombre de ressources obtenues est un contrôle correct (permis); long microstowait; // Lock synchronisé (Mutex ()) {// Temps actuel NowMicros = stopwatch.readmicros (); // jugez si la ressource peut être obtenue dans le délai d'attente si (! Canacquire (NowMicros, Timeoutmicros)) {return false; } else {// La ressource peut être obtenue, recalculé la ressource et renvoyé le temps de sommeil requis par le thread actuel MicroStowait = ReserveAndgetWaitLength (permis, NowMicros); }} // le chronomètre du sommeil.SleepMicrosunInterruply (MicroStowait); Retour Vrai; }Déterminez s'il faut obtenir le jeton:
Canacquire booléen privé (Long Nowmicros, Long TimeoutMicros) {// Dans le premier temps de ressource peut être obtenu - le temps d'attente <= le temps actuel peut être obtenu avant que la ressource puisse être obtenue Return QueryArlistavailable (NOWMICROS) - TimeoutMicros <= NowMicros;}Ratelimiter Default Implémentation Classe queyarlistAvailable est de prendre la variable de membre NextFreeTticketMicros
Obtenez le jeton et calculez l'opération de temps d'attente requise:
Final Long ReserveAnDgetWaitLength (INT Permis, Long NowMicros) {// Obtenez le temps d'obtenir la prochaine fois Long DimentAvailable = ReserveArlistAnSavailable (Permits, NowMicros); // Calculez le temps de sommeil requis pour que le thread actuel renvoie max (momentAvailable - NowMicros, 0);} Final Long ReserveArlistaliseAdable (int reebwesperMits, Long NowMicros) {// recalcule le nombre de jetons dans le seau StoredPermits Resync (NowMicros); long returnValue = nextFreeTticketMicros; // le nombre de jetons consommés cette fois à double stockage de PermitStospennd = min (requiredPermits, this.storedpermits); // recalcule l'heure pour obtenir la prochaine fois que NextFreeTticketMicros double FreshPermits = requiredPermits - StoredPermitStospend; Long WaitMicros = StoredPermitStowaitTime (this.storedPermits, StoredPermitStospend) + (long) (FreshPermits * stableIntervalmicros); this.nextfreeticketmicros = longmath.saturatedadd (nextfreeticketmicros, waitmicros); // Réduisez le nombre de jetons dans le seau this.storedPermits - = StoredPermitStospend; retour returnValue; }Implémentez un intercepteur de limite de courant Spring MVC simple
Implémentez un gestionnaire de gestionnaire, créez un limiteur de courant Ratelimiter dans le constructeur
public SimpleratelimitInterceptor (int rate) {if (rate> 0) globalRatelimiter = ratelimiter.Create (rate); Sinon, jetez une nouvelle RuntimeException ("le taux doit être supérieur à zéro");}Appelez la méthode Tryacquire du limiteur actuel dans la pré-main
Public Boolean Prehandle (demande httpservletRequest, réponse httpservletResponse, gestionnaire d'objets) lève exception {if (! GlobalRatelimiter.tryacquire ()) {LoggerUtil.log (request.getRequeSturi () + "Demande dépasse le taux de limiter actuel"); retourne false; } return true; }Configurez l'intercepteur de limite actuel dans Dispatcher-Servlet.xml
<MVC: Interceptors> <! - Current Limit Interceptor -> <MVC: interceptor> <mvc: mapping path = "/ **" /> <ean> <constructor-arg index = "0" value = "$ {totalrate}" /> </ bean> </ mvc: interceptor> </mvc: intercepteurs>Version complexe de Spring MVC Current Limit Interceptor
Utiliser des propriétés pour passer dans l'expression de l'URL interceptée -> Taux
<mvc: interceptor> <mvc: mapping path = "/ **" /> <ean> <! - Url Current limite -> <propriété name = "urlproperties"> <props> <prop key = "/ get / {id}"> 1 </ prop> <pop key = "/ post"> 2 </ proper> Créez un limiteur de courant Ratelimiter correspondant pour chaque expression d'URL. L'expression URL est encapsulée comme org.springframework.web.servlet.mvc.condition.PatternSrequestCondition. PatternSrequestCondition est une classe utilisée dans Dispatcherservlet de SpringMVC pour faire correspondre les demandes et les contrôleurs. Il peut déterminer si la demande est conforme à ces expressions URL.
Dans la méthode de pré-maintenance intercepteur
// Le chemin de demande actuel String lookuppath = urlpathhelper.getLookuppathForRequest (request); // itérera sur le motif de requestCondition correspondant à toutes les expressions d'URL (motifs de PatternCondution {// faire une liste de correspondance <string> correspond à Urlratemap.KeySet ()) {// faire une liste de correspondance <string> Matches = PatternSrequestCondition.GetMatchingPatterns (lookuppath); if (! Matches.iSempty ()) {// Si le match réussit, obtenez le jeton du limiteur actuel correspondant if (urlratemap.get (motifSrequestCondition) .tryCQuire ()) {loggerUtil.log (lookuppath + "demande assorti à" + jointer.on ("). limiteur "); } else {// a échoué pour obtenir le token loggerUtil.log (lookuppath + "la demande dépasse" + jointer.on (","). join (patronsRequestCondition.getPatterns ()) + "Rate de limiteur de courant"); retourne false; }}}Classes d'implémentation spécifiques
Veuillez voir Github
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.