Durante aplicaciones de alta disponibilidad y la interfaz API es crítico. Si proporcionamos una interfaz, el tráfico se enfrentó repentinamente con un crecimiento explosivo, en este caso, no sólo afectará a la velocidad de acceso del sitio, e incluso puede hacer que el servidor accidente, por lo que todos los usuarios normalmente no pueden acceder.
En este caso, algunos estudiantes dijeron: "Podemos configurar la máquina mediante el aumento o aumentar para resolver este problema." En algunos casos esto es realmente una opción. Sin embargo, cuando usamos una interfaz o aplicación, no necesitamos sólo a través de medios técnicos (idempotencia, fusibles, etc.) para mejorar su estabilidad, garantizando al mismo tiempo que otras razones inesperadas (como el código escribiendo nuevos colegas provocar accidentes etc.) causado problemas.
Las siguientes situaciones, las restricciones de frecuencia pueden ayudarnos a garantizar mejor la disponibilidad de la API:
- Los usuarios que utilicen un guión, un gran número de solicitudes enviadas a nosotros.
- Los usuarios nos envían muchas peticiones de datos de baja prioridad interfaz, y esperamos que estas solicitudes de baja prioridad con un impacto mínimo en nuestras solicitudes de interfaz de alta prioridad (como los proveedores de electricidad deben asegurarse proceso de pedido es normal, la otra interfaz tiene prioridad nivel natural más baja que un solo las interfaces relacionadas con el proceso).
- razones repentinos, normalmente no pueden acceder a todas las interfaces de forma simultánea, lo que requiere la solicitud de menor prioridad de descarte temporal (por supuesto
Nginx
niveles es alcanzable).
Introducción de cubetas de fichas
Principio algoritmo de cubetas de fichas es que el sistema será a una velocidad constante para cubo (cubo) en tokens (token), si la solicitud a procesar, a partir de la necesidad de obtener una muestra cubo, cuando el cubo no es tan tarjetas son deseables, la denegación de servicio (denegación de servicio).
características:
- Cuando
bucket
completo, ya no será colocadotoken
, es decir,token
el número no exceda de labucket
capacidad máxima. - Desde
token
un período de tiempo es limitado, por lo que incluso si se produce un flujo repentino, puede ser servicios bien protegidas.
implementación
Para la realización del colector de testigos, que se utiliza comúnmente en dos formas:
el primer
Iniciar un hilo de fondo, de acuerdo con un cierto granularidad tiempo, para continuar con el 固定大小
cubo (cubo) para aumentar el token (token), hasta que alcance 桶
su capacidad máxima.
Este enfoque no sólo alcanzar un punto poco engorroso, la necesidad de mantenimiento adicional de un guión, y en ausencia de una solicitud, el hilo continuará para comprobar las actualizaciones de emergencia, si la llave bajo el número relativamente grande de casos, tienen un mayor impacto en el rendimiento de la CPU .
El segundo (caso de papel)
En cada visita, el tiempo y la frecuencia almacenada en la visita redis
y la siguiente nueva solicitud de acceso, la comparación 当前时间
, y 上次请求时间
entre las dos diferencias de tiempo se pueden usar número de token, y almacenan los nuevos resultados redis
.
la implementación del código
initNum
El tamaño inicial de la cubetaexpire
Unidad de tiemponowTime
El tiempo de acceso actuallimitData['time']
La última vez que la solicitud
<? PHP espacio de nombres App \ Componentes; uso Yii \ Base \ componente; clase RateLimiter la extiende el componente { público $ Redis = nula ; pública $ cacheKey = nula ; // Número de visitas por minuto por el usuario A SOLO bajo // unidad de tiempo, una sola el número de usuarios para acceder al público $ initNum = 30 ; // unidad de tiempo de tiempo // unidad pública $ expiran el = 60 ; / * * . * RateLimiter constructor * @param string $ initNum * @Param string $ expiran * / público en función __construct ( $ cacheKey = '', $ initNum = '', $ expiran = '' ) { si ( vacío ( $ cacheKey )) { retorno falsa ; } $ This -> Redis = \ Yii :: $ aplicación -> ReDiS; $ this -> initNum = $ initNum ?? $ this -> initNum; $ this -> expire = $ expire ?? $ this -> expirado; $ this -> cacheKey = $ cacheKey ; } / * * * Controlador * @return array * / público en función de controlador on () { $ ret = self :: _ límite ( $ this -> cacheKey, $ this -> initNum, $ this -> expirará); si ( vacío ( $ ret [ 'status' ])) { retorno falsa ; } Devolver cierto ; } Privada función _limit ( $ cacheKey = '', $ initNum = '', $ expiran = '' ) { $ nowtime = Time (); $ del este -> redescubrir> Watch ( $ cacheKey ); $ redisData = $ al este -> redescubrir> get ( $ cacheKey ); $ limitData = redisData $ ? json_decode ( $ redisData , true ): [ 'NUM' => $ initNum , 'tiempo' => $ nowtime ]; // (frecuencia de acceso por unidad de tiempo / unidad de tiempo) * (tiempo actual - hora del último acceso) = el número de visitas desde la última petición de aumento de $ addNum = ( $ initNum / $ del expiran ) * ( $ nowtime- $ limitData[ 'Time' ]); $ newNum = min ( $ initNum , (( $ limitData [ 'NUM'] - 1) +. $ AddNum )); IF ( $ newNum <= 0 ) { retorno [ 'Status' => en false , 'MSG' => 'actualidad token de que se agote! ' ]; } $ LimitData = json_encode ([' NUM '=> $ newNum ,' Time '=> $ nowtime ]); $ del este -> redescubrir> Multi (); $ del este -> redescubrir> SET ( $ cacheKey , $ limitData ); la presente $ -> redescubrir> Exec ()) { retorno [ 'Estado' => false ,' MSG '=>' demasiadas veces la frecuencia de visita! ' ]; } Volver [' Estado => true , 'MSG' => 'Aceptar' ]; } }
resumen
límite de frecuencia Token Bucket es API
uno de los diseño de la interfaz importante en la política de seguridad, pero por diferentes escenarios de negocio y debe utilizar el método más adecuado (tal como contraseña es incorrecta, un día sólo cinco intentos, este contador es la frecuencia del límite mejor opción), todo lo que no es absoluta.