Skip to content
This page has been auto-translated and may contain errors.View in English

Contadores de ventana fija

Un estacionamiento con cinco lugares y una barrera. Cada treinta segundos la barrera se reinicia y los lugares quedan libres otra vez.

Eso es un contador de ventana fija, el algoritmo de limitación de tasa más simple que existe. Cuenta las solicitudes dentro de una ventana de duración fija, rechaza todo lo que exceda el límite, y reinicia el conteo cuando la ventana termina.

Observando cómo se llena una ventana

Un límite de cinco solicitudes por ventana de treinta segundos:

TiempoQué llegaConteoResultado
0s1 solicitud1Aceptada
5s2 solicitudes3Aceptada
15s2 solicitudes5Aceptada, y la barrera baja
25s1 solicitud5Rechazada, la ventana está llena
30sSe abre la ventana 20El conteo se reinicia

El estado involucrado son dos valores: en qué punto de la ventana estás, y el conteo hasta ahora. Nada se traslada de la ventana que terminó.

Esa simplicidad es todo el atractivo. Barato de almacenar, barato de verificar, y difícil de confundir.

JunoObservando cómo se llena una ventana Fíjate en la solicitud de los 25 segundos. Se rechaza cuando faltan cinco segundos para que termine la ventana, y si hubiera esperado seis segundos habría pasado sin problema.

Eso es el algoritmo siendo tajante, no injusto. No tiene noción de "casi", solo de si algo está dentro de esta ventana o no.

JunoObservando cómo se llena una ventana Que "no se recuerde nada de la ventana anterior" es justo lo que hace que esto sea barato de ejecutar. Un contador y una marca de tiempo por cliente, y un reinicio que descarta el valor anterior.

Compara eso con guardar una marca de tiempo por cada solicitud, que es lo que necesita el siguiente algoritmo. Esa diferencia de almacenamiento es el punto central de toda la comparación.

JunoObservando cómo se llena una ventana Hay un segundo problema junto al de las ráfagas, y es su imagen espejo: la sequía. Cinco solicitudes que llegan en el primer segundo de una ventana dejan veintinueve segundos en los que un cliente legítimo es rechazado a pesar de que el servicio está inactivo.

Por eso las ventanas fijas son duras con el tráfico que llega en ráfagas pero que es razonable, que es la mayor parte del tráfico real. Una página que carga seis recursos a la vez gasta todo el presupuesto de una ventana al instante.

También vale la pena decidir si las ventanas se alinean al reloj o a la primera solicitud de cada cliente. Las ventanas alineadas al reloj hacen que la ventana de todos los clientes se reinicie en el mismo instante, lo que sincroniza los reintentos de todos en un solo pico.

La ráfaga en el límite

Ahora observa dos ventanas consecutivas, con el mismo límite de cinco cada treinta segundos:

TiempoVentanaSolicitudesConteo acumulado
50s224
55s226, así que se aceptan 5
60sSe abre la 322

Fíjate en el reloj y no en las ventanas. Entre los 50 y los 60 segundos, se aceptaron siete solicitudes.

El límite era cinco cada treinta segundos, y llegaron siete en diez.

Nada falló. Las solicitudes al final de la ventana dos y al inicio de la ventana tres están en ventanas distintas, así que ningún conteo superó nunca el cinco. El algoritmo hizo exactamente lo que se le indicó.

Eso es el problema del límite entre ventanas, y es la debilidad que define este enfoque. En el peor caso, un cliente envía el límite completo justo antes de un reinicio y el límite completo justo después, colando el doble del límite en un instante.

JunoLa ráfaga en el límite El truco está en desde dónde miras. Dentro de cada ventana todo es correcto y está dentro del límite.

Da un paso atrás y observa un tramo de tiempo real que cruce el límite entre ventanas, y verás que el límite nunca se aplicó realmente ahí.

JunoLa ráfaga en el límite Vale la pena ponerle un número: el peor caso es el doble de tu límite en un instante, así que dimensiona el límite pensando en eso. Si tu servicio puede sobrevivir a 200 solicitudes en una ráfaga, un límite de ventana fija de 100 es defendible.

Un atacante que conoce la duración de tu ventana puede apuntar deliberadamente a ese límite, y la duración de la ventana es fácil de inferir observando cuándo ocurre el reinicio.

JunoLa ráfaga en el límite Esto se puede reproducir exactamente, no es solo teoría. Medido contra un límite de ventana fija de 100, enviar solicitudes atravesando el límite entre ventanas permite pasar 200 solicitudes.

El registro de ventana deslizante permite 100 y el contador de ventana deslizante 101, que es la comparación sobre la que se construyen los siguientes capítulos.

La razón para seguir usando ventanas fijas de todos modos es el costo: un entero y una marca de tiempo por cliente, incrementados de forma atómica. En la escala donde más importa la limitación de tasa, esa diferencia en almacenamiento y coordinación no es pequeña.

La respuesta habitual en producción es una ventana fija dimensionada para que el doble del límite sea sobrevivible, con algo más preciso en los pocos endpoints donde una ráfaga causa daño real.

Ponlo a prueba

Una API permite 10 solicitudes por ventana de 60 segundos, alineada al reloj, de modo que las ventanas empiezan en cada minuto exacto.

  1. Un cliente envía 10 solicitudes a las 12:00:59 y 10 más a las 12:01:01. ¿Cuántas se aceptan, y se rompió el límite?
  2. Un cliente envía sus 10 solicitudes a las 12:00:00. ¿Qué pasa con su solicitud de las 12:00:30?
  3. Necesitas garantizar que ningún cliente reciba nunca más de 10 solicitudes en ningún tramo de 60 segundos. ¿Puede lograrlo una ventana fija?
Compara tus respuestas

1. Se aceptan las 20, y no se rompió ninguna regla. Las primeras diez caen en la ventana de las 12:00 y las segundas diez en la de las 12:01, así que ningún conteo pasó de 10.

Llegaron veinte solicitudes en dos segundos. Eso es la ráfaga en el límite entre ventanas, y no hizo falta nada más ingenioso que notar cuándo cambia el minuto.

2. Rechazada. La ventana está llena y le quedan treinta segundos por correr. El servicio está completamente inactivo y aun así el cliente tiene que esperar, que es la sequía que viene junto con la ráfaga.

3. No. No con una ventana fija, sea cual sea el límite. Cualquier tramo de tiempo que cruce un límite entre ventanas puede dejar pasar hasta el doble del límite, y eso es una propiedad de dividir el tiempo en bloques fijos, no un problema de ajuste.

Conseguir esa garantía significa medir contra una ventana que se mueve junto con la solicitud en lugar de un bloque fijo en un calendario, y de eso trata el siguiente capítulo.

Hacia dónde vamos ahora

Las ventanas fijas son baratas, simples, y se equivocan hasta por un factor de dos en el límite entre ventanas. Que eso importe o no depende de lo que haga el endpoint.

Antes de arreglarlo, vale la pena construir uno. Construyendo un limitador de tasa convierte este algoritmo en un middleware de Express funcional, con los encabezados que un cliente necesita para comportarse bien.