Algoritmo de limitador actual
Actualmente, hay dos algoritmos de limitador de corriente comunes: algoritmo de cubo de token y algoritmo de cubo con fugas. La principal diferencia es que el algoritmo de cubo con fugas puede limitar por la fuerza la tasa de solicitud y las solicitudes de explosión suaves, mientras que el algoritmo de cubo token permite una cierta cantidad de solicitudes de explosión al limitar la tasa promedio.
A continuación se encuentran dos diagramas de algoritmos que se encuentran en Internet, que se pueden distinguir fácilmente de las características de estos dos algoritmos.
Algoritmo de cubo de fuga
Algoritmo de cubo
Para las interfaces, generalmente se permite procesar una cierta cantidad de solicitudes de explosión, y solo se requiere la tasa promedio para limitar, por lo que el algoritmo de cubo de token es más común.
Herramienta de algoritmo de cubo de token ratelimitan
La clase de implementación del algoritmo de cubo de token que utilizo más comúnmente utilizado es el ratelimiter de Google Guava. La guayaba no solo implementa el algoritmo de cubo de token, sino también en caché, nuevas clases de recolección, clases de herramientas concurrentes, clases de procesamiento de cadenas, etc. Es un poderoso conjunto de herramientas
La API de Ratelimiter puede ver la introducción de Guava Ratelimiter en la red de programación concurrente
Análisis del código fuente de Ratelimiter
Por defecto, los atributos más centrales de Ratelimiter son dos NextFreeticketMicros. El tiempo de token se puede obtener la próxima vez y el número de fichas en el cubo de Permits almacenados.
Determine si debe obtener el token:
Cada vez que obtienes un token, calcule el tiempo más rápido para obtener el token la próxima vez en función del número de fichas en el cubo. Al determinar si se puede obtener el recurso, simplemente compare NextFreeticketMicros con la hora actual.
Obtener operación de token:
Para obtener el token, calcule el número de tokens nuevos basados en NextFreeticketMicros y la hora actual, escriba el número de token de token actual y recalcule NextFreeticketMicros. Si hay un token en el balde, escriba el tiempo actual y reduzca el número de tokens obtenidos por esta solicitud.
Al igual que la clase AQS en Java, el núcleo de RatElimiter es el método de Tryacquire
Public boolean tryacquire (int permite, tiempo de espera largo, unidad de tiempo de tiempo) {// intenta obtener el tiempo de espera máximo largo tiempo de espera largo = max (unit.tomicros (tiempo de espera), 0); // Verifique si el número de recursos obtenidos es correcto CheckPermits (permisos); MicroStoswait largo; // bloquear sincronizado (mutex ()) {// TIEMPO Current Long nowMicros = stopWatch.ReadMicros (); // juzga si el recurso se puede obtener dentro del tiempo de tiempo de espera si (! Canacquire (NowMicros, TimeOutMicros)) {return false; } else {// El recurso se puede obtener, recalcular el recurso y devolver el tiempo de sueño requerido por el hilo actual microTowait = reservaandgetwaitLength (permisos, nowmicros); }} // El stopwatch de sueño. devolver verdadero; }Determine si debe obtener el token:
canacquire booleano privado (Long NowMicros, tiempo de tiempo de espera largo) {// al tiempo de recurso más temprano se puede obtener - El tiempo de espera <= la hora actual se puede obtener antes de que el recurso se pueda obtener de devolución de consulta Avalable (NowMicros) - Tiempo de tiempo de espera <= Nowmicros;}RatElimiter de implementación predeterminada de la clase de consulta AleAnVailable es tomar la variable del miembro NextFreeticketMicros
Obtenga el token y calcule la operación del tiempo de espera requerida:
Final Long ReservanDgetWaitLength (int lo permite, long Nowmicros) {// Obtenga el tiempo para obtener la próxima vez larga Momento Avalible = ReserveLiDVailable (Permisos, NowMicros); // Calcule el tiempo de sueño requerido para que el hilo actual devuelva Max (MomentAplailable - NowMicros, 0);} Final Long ReserveArliDAVailable (int requerido Permits, Long NowMicros) {// recalcular el número de tokens en el cubo almacenado Permits Resync (NowMicros); larga returnValue = nextFreeticketMicros; // El número de tokens consumidos esta vez Double StoredPermitStaStoSpend = min (requiredPermits, this.RededPermits); // Recalcule el tiempo para obtener la próxima vez NEXTFREETICKETTMICROS DOBLE FreshPermits = requirirpermits - StoredPermitStoSpend; Long WaitMicros = StoredPermitStowaItTime (this. this.nextfreeticketmicros = longMath.SaturatedAdd (nextFreeticketMicros, WaitMicros); // Reduce el número de tokens en el balde. return returnValue; }Implementar un interceptor de límite de corriente MVC de Spring Spring simple
Implemente un HandlerInterceptor, cree un limitador de corriente Ratelimiter en el constructor
public SimpleRAtelImitInterceptor (int tasa) {if (tasa> 0) globalRatelimiter = ratelimiter.create (tasa); de lo contrario, tire la nueva runtimeException ("la tasa debe mayor que cero");}Llame al método Tryacquire del limitador actual en Prehandle para determinar si la tasa límite lo ha excedido
Public Boolean PreHandle (HttpServletRequest Solicitud, respuesta httpservletResponse, manejador de objetos) lanza la excepción {if (! GlobalRateLimiter.tryacquire ()) {loggerUtil.log (request.getRequesturi ()+"Solicitud excede la tasa de limitador actual"); devolver falso; } return verdadero; }Configurar el interceptor de límite actual en despachador-servlet.xml
<mvc: interceptores> <!-Interceptor de límite actual-> <mvc: interceptor> <mvc: mapping rath = "/**"/> <Bean> <constructor-arg index = "0" value = "$ {TotalRate}"/> </bean> </mvc: Interceptor> </mvc: Interceptors>Versión compleja del Interceptor de límite de corriente de Spring MVC
Use las propiedades para pasar en la expresión de URL interceptada -> tasa de tasa
<mvc: interceptor> <mvc: mapping path = "/**"/> <Bean> <!-Límite actual de URL URL-> <Property Name = "UrlProperties"> <Props> <Prop key = "/get/{id}"> 1 </prop> <pp key = "/post"> 2 </prop> </props> </propiedad> Cree un limitador de corriente de ratelimitador correspondiente para cada expresión de URL. La expresión de URL se encapsula como org.springframework.web.servlet.mvc.condition.patternsrequestCondition. PatternsRequestCondition es una clase utilizada en DispatcherServlet de SpringMVC para que coincida con las solicitudes y controladores. Puede determinar si la solicitud cumple con estas expresiones de URL.
En el método de prehandilla del interceptor
// La cadena de ruta de solicitud actual lookUppath = urlpathhelper.getLookuppathForRequest (request); // iterar sobre el patrón de la información correspondiente a todas las expresiones de url (patrutssrequestcondition patrutssrequestCondition PatternsRequestCondition.getMatchingPaterns (Lookuppath); if (! Matches.isEmpty ()) {// Si la coincidencia es exitosa, obtenga el token del limitador de corriente correspondiente if (urlrateMap.get (PatternSequestCondition) .ytryacquire ()) {loggerutil.log (lookuppath + "Solicitud" + " + un Joiner.on (", "). limitador "); } else {// No se pudo obtener el token loggerutil.log (lookUppath + "solicitud excede" + Joiner.on (","). Join (PatternsRequestCondition.getPatterns ()) + "Tasa de limitador actual"); devolver falso; }}}Clases de implementación específicas
Por favor vea GitHub
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.