El propósito de la limitación actual es proteger el sistema limitando la velocidad del acceso/solicitudes concurrentes o limitando la velocidad de las solicitudes dentro de una ventana de tiempo. Una vez que se alcanza la tasa de limitación, se puede negar el servicio.
Hace unos días, leí un plan para usar Guawa para lograr una limitación de flujo de aplicación única. Referencia "Redis in Action" para implementar una versión JEDIS, todas las cuales son restricciones a nivel empresarial. Estrategias de limitación actuales comunes en escenarios reales:
Límite de corriente de la capa de acceso Nginx
De acuerdo con ciertas reglas, como el número de cuenta, IP, la lógica de llamadas del sistema, etc., para limitar la corriente en el nivel Nginx
Límite actual del sistema de aplicación de negocios
Control del tráfico a través del código de negocios Este tráfico puede llamarse semáforo, que puede entenderse como un bloqueo, que puede limitar cuántos procesos se puede acceder a un recurso simultáneamente.
Implementación del código
importar redis.clients.jedis.jedis; import redis.clients.jedis.transaction; import redis.clients.jedis.zparams; import java.util.list; import java.util.uUuid;/** * @Email [email protected] * @data 2017-08 */public class Redisratelimiter {private sting string bucket. "BALDE"; String Final STATIC static privado bucket_count = "bucket_count"; String Final STATIC privado Bucket_monitor = "Bucket_monitor"; Cadena estática adquiretokokenfrombucket (JEDIS JEDIS, INT límite, tiempo de tiempo largo) {String Identifier = uuid.randomuuid (). toString (); long Now = System.CurrentTimemillis (); Transacción transacción = jedis.multi (); // Eliminar Semaphore Transaction.zremRangebysCore (bucket_monitor.getBytes (), "-inf" .getBytes (), string.valueOf (ahora - timeout) .getBytes ()); ZParams Params = new Zparams (); params.weaksbydouble (1.0,0.0); transaccion.zinterstore (cubo, parámetros, bucket, bucket_monitor); // contrarrestar transacciones de autoincremento.incr (bucket_count); Lista <S Object> Results = Transaction.exec (); contador largo = (largo) results.get (results.size () - 1); transacción = jedis.multi (); transacción.zadd (bucket_monitor, ahora, identificador); transacción.zadd (cubo, contador, identificador); transaccion.zrank (cubo, identificador); resultados = transacción.exec (); // Obtenga la clasificación para determinar si la solicitud ha obtenido el rango largo de semáforo = (largo) resultados.get (results.size () - 1); if (rank <limit) {Return Identifier; } else {// No se obtuvo semáforo, se puso en Redis antes de limpiar la transacción = jedis.multi (); transacción.zrem (bucket_monitor, identificador); transaccion.zrem (cubo, identificador); transacción.exec (); } return null; }}
Llamar
Llamada de la interfaz de prueba
@GetMapping ("/") public void índice (respuesta httpservletreSponse) lanza ioexception {jEdis jEdis = jedispool.getResource (); String token = redisratelimiter.acquiretokenfrombucket (jedis, límite, tiempo de espera); if (token == null) {Response.sendError (500); } else {// Todas tu lógica de negocios} jedispool.returnResource (jedis);}mejoramiento
Optimizar el código con Interceptor + Anotación
Interceptador
@ConfigurationStatic Class WebMVCConfigurer extiende WebMVCConfigurerAdapter {private logger logger = loggerFactory.getLogger (webMVCConfigurer.class); @Autowired Private Jedispool Jedispool; public void AddInterceptors (InterceptorRegistry Registry) {Registry.addinterceptor (new HandlerIntercepteRAdapter () {public boolean prehandle (httpservletRequest request, httpServletResponse respuesta, manejador de objetos) Excepción {HandLermethod HandLermethod = ((Handlermethod) Handler; Method de Handlermethod (Method = Handlermethod (HandLermethod (HandLermethod; RatElimiter RatElimiter = Method.getAnnotation (RatElimiter.Class); Tiempo de espera); }}Anotación de definición
/** * @email [email protected] * @data 2017-08 * Annotación límite actual */@Target (elementType.method) @Retention (retentionPolicy.Runtime) @DocumentPublic @interface ratelimiter {int limit () predeterminado 5; int timeout () predeterminado 1000;}
usar
@RatelImiter (Limit = 2, TimeOut = 5000) @getMapping ("/Test") public void test () {}Prueba concurrente
Herramientas: Apache-JMeter-3.2
Nota: La interfaz que no ha obtenido el semáforo devuelve 500, el estado es rojo, la interfaz que ha obtenido el semáforo retorna 200, el estado es verde.
Cuando el semáforo de solicitud de límite es 2, se envían 5 hilos:
Cuando el semáforo de solicitud de límite es 5, se envían 10 hilos:
material
Implementación basada en Reids + Lua
Resumir
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.