Le but de la limitation de courant est de protéger le système en limitant la vitesse d'accès / demandes simultanées ou de limiter la vitesse des demandes dans une fenêtre de temps. Une fois le taux de limitation atteint, le service peut être refusé.
Il y a quelques jours, j'ai lu un plan pour utiliser Guawa pour atteindre une limitation de flux unique. Référence "Redis en action" pour implémenter une version Jedis, qui sont toutes des restrictions au niveau commercial. Stratégies de limitation de courant commun dans les scénarios réels:
Limite de courant de la couche d'accès Nginx
Selon certaines règles, telles que le numéro de compte, l'IP, la logique des appels système, etc., pour limiter le courant au niveau Nginx
Système d'application d'entreprise Limite actuelle
Contrôlant le trafic via le code commercial Ce trafic peut être appelé un sémaphore, qui peut être compris comme un verrou, qui peut limiter le nombre de processus d'une ressource accessible simultanément.
Implémentation de code
Importer redis.clients.jedis.jeded; import redis.clients.jedis.transaction; import redis.clients.jedis.zparams; importer java.util.list; import java.util.uuid; / ** * @email [email protected] * @data 2017-08 * / classe publique redisratELIMIT "SEAU"; String final statique privé bucket_count = "bucket_count"; chaîne finale statique privée bucket_monitor = "bucket_monitor"; Static String acquireTokenFrombucket (Jedis Jedis, int limit, long timeout) {String identifier = uuid.randomuuid (). toString (); Long Now = System.Currenttimemillis (); Transaction transaction = jedis.multi (); // Delete Semaphore Transaction.ZremRangeBysCore (Bucket_Monitor.getBytes (), "-inf" .getBytes (), String.ValueOf (maintenant - Timeout) .getBytes ()); ZParams params = new ZParams (); params.wemblesByDouble (1.0,0.0); transaction.zinterStore (seau, params, godet, bucket_monitor); // Counter Self-Increment Transaction.incr (Bucket_Count); List <objet> résultats = transaction.exec (); compteur long = (long) results.get (results.size () - 1); transaction = jedis.multi (); transaction.zadd (bucket_monitor, maintenant, identifiant); transaction.zadd (seau, compteur, identifiant); transaction.zrank (seau, identifiant); résultats = transaction.exec (); // obtient le classement pour déterminer si la demande a obtenu le semaphore long Rank = (long) results.get (results.size () - 1); if (rank <limit) {return identifier; } else {// Aucun sémaphore n'a été obtenu, mis dans redis avant la transaction de nettoyage = jedis.multi (); transaction.zrem (bucket_monitor, identifiant); transaction.zrem (seau, identifiant); transaction.exec (); } return null; }}
Appel
Test d'appel d'interface
@GetMapping ("/") public void index (HttpServletResponse Response) lève ioException {Jedis Jedis = jedispool.getResource (); String token = redisratelimiter.acquiretokenfrombucket (Jedis, limite, délai d'attente); if (token == null) {réponse.Senderror (500); } else {// too votre logique commerciale} jedispool.returnResource (Jedis);}optimisation
Optimiser le code avec intercepteur + annotation
Intercepteur
@Configurationstatic class webmvcconfigurer étend webmvcconfigurerAdapter {private logger logger = loggerfactory.getLogger (webmvcconfigurer.class); @Autowired Private Jedispool Jedispool; public void addInterceptors (InterceptorRegistry Registry) {Registry.AddInterceptor (new HandlerInterceptorAdapter () {Public Boolean Preandle (HttpservletRequest Request, HttpservletResponse Réponse, Handler d'objet) exception {HandlerMethod HandlerMethod = (HandlerMethod) Handler; méthode méthode = handlerMet Ratelimiter Ratelimiter = Methand.getannotation (Rateliter.Class); (token == null) {Response.Sendorror (500); }}Annotation de définition
/ ** * @email [email protected] * @data 2017-08 * Annotation de limite actuelle * / @ Target (elementType.Method) @retention (RetentionPolicy.Runtime) @DocumedPublic @Interface Ratelimiter {int limite () Default 5; int timeout () par défaut 1000;}
utiliser
@Ratelimiter (limite = 2, timeout = 5000) @getmapping ("/ test") public void test () {}Tests simultanés
Outils: Apache-JMeter-3.2
Remarque: L'interface qui n'a pas obtenu le sémaphore renvoie 500, l'état est rouge, l'interface qui a obtenu le sémaphore renvoie 200, l'état est vert.
Lorsque le sémaphore de demande limite est de 2, 5 threads sont envoyés:
Lorsque le sémaphore de demande limite est de 5, 10 threads sont envoyés:
matériel
Implémentation basée sur Reids + Lua
Résumer
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.