O objetivo da limitação atual é proteger o sistema, limitando a velocidade de acesso/solicitações simultâneas ou limitando a velocidade das solicitações dentro de uma janela de tempo. Uma vez atingida a taxa limitadora, o serviço pode ser negado.
Alguns dias atrás, li um plano para usar o Guawa para obter limitação do fluxo de aplicação única. Referência "Redis em ação" para implementar uma versão JEDIS, todas as quais são restrições no nível dos negócios. Estratégias de limitação atuais comuns em cenários reais:
Limite de corrente da camada de acesso nginx
De acordo com certas regras, como número da conta, IP, lógica de chamada do sistema, etc., para limitar a corrente no nível Nginx
Limite atual do sistema de aplicativos de negócios
Controlando o tráfego através do código de negócios Esse tráfego pode ser chamado de semáforo, que pode ser entendido como um bloqueio, o que pode limitar quantos processos um recurso pode ser acessado simultaneamente.
Implementação de código
importar redis.clients.jedis.jedis; importar redis.clients.jedis.transaction; importar redis.cliients.jedis.zparams; importar java.util.list; import java.util.uuid;/** * @Email [email protected] * @data7-208 ** ** ** [email protected] * @data7-08 "BALDE"; String final estática privada bucket_count = "bucket_count"; String final estática privada bucket_monitor = "bucket_monitor"; Static String adquireTokenFombucket (Jedis Jedis, INT limite, tempo limite longo) {String Identifier = uuid.randomuuid (). ToString (); long now = System.currenttimemillis (); Transação transaction = jedis.multi (); // excluir semáforo transaction.zremrangeByScore (bucket_monitor.getbytes (), "-inf" .getBytes (), string.valueof (agora - timeout) .getBytes ()); ZParams params = new zParams (); params.weightsbydouble (1.0,0.0); transaction.zinterstore (bucket, params, bucket, bucket_monitor); // contra transação de auto-incremento.inCr (bucket_count); List <ject> resulta = transaction.exec (); contador longo = (longo) resultados.get (resulta.size () - 1); transação = jedis.multi (); transaction.zadd (bucket_monitor, agora, identificador); transaction.zadd (balde, contador, identificador); transaction.zrank (balde, identificador); Resultados = transaction.exec (); // Obtenha a classificação para determinar se a solicitação obteve a classificação semáforo longa = (long) resultados.get (resultados.size () - 1); if (rank <limite) {retornar identificador; } else {// nenhum semáforo foi obtido, colocado em redis antes de limpar a transação = jedis.multi (); transaction.zrem (bucket_monitor, identificador); transaction.zrem (balde, identificador); transaction.exec (); } retornar nulo; }}
Chamar
Chamada de interface de teste
@GetMapping ("/") INDEX PUBLICO (HTTPSERVletResponse Response) lança IoException {Jedis jedis = Jedispool.getResource (); String token = redisratelimiter.acquireTokenFombucket (Jedis, limite, tempo limite); if (token == null) {Response.Senderror (500); } else {// TODO sua lógica de negócios} Jedispool.returnResource (Jedis);}otimização
Otimizar o código com a anotação interceptora +
Interceptor
@ConfigurationStatic class WebMvcConfigurer estende webmvcConfigureRAdApter {private logger logger = loggerFactory.getLogger (webmvcConfigurer.class); @Autowired Private Jedispool Jedispool; public void addinterceptores (interceptorRegistry Registry) {Registry.addintercept (new HandlerInterceptAdApter () {public boolean pré -Handle (httpServletRequest solicitação, httpServLeSponse Response, manipulador de objeto) lança a exceção {manutenção manuten; Ratelimiter ratelimiter = Method.getannotation (ratelimiter.class); if (token == NULL) {Response.sendror (500); }}Anotação de definição
/** * @Email [email protected] * @Data 2017-08 * Anotação do limite atual */@Target (ElementType.method) @retention (retentionPolicy.Runtime) @DocumentEdPublic @Interface Ratelimiter {int limite () default 5; int timeout () padrão 1000;}
usar
@Ratelimiter (limite = 2, timeout = 5000) @getMapping ("/test") public void test () {}Testes simultâneos
Ferramentas: Apache-Jmeter-3.2
Nota: A interface que não obteve o semáforo retorna 500, o status é vermelho, a interface que obteve o semáforo retorna 200, o status é verde.
Quando a solicitação de limite semáforo é 2, 5 threads são enviados:
Quando a solicitação de limite semáforo é 5, 10 threads são enviados:
material
Implementação baseada em reids + lua
Resumir
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.