Nginx - Cosa fa l'opzione di nodelay quando si limitano le richieste?


11

Con nginx HttpLimitReq le richieste del modulo possono essere limitate dall'IP. Tuttavia, non capisco cosa fa l'opzione "nodelay".

Se le richieste in eccesso entro il limite di burst del limite non sono necessarie, è necessario utilizzare il nodelay

limit_req   zone=one  burst=5  nodelay;

Risposte:


11

La documentazione qui ha una spiegazione che suona come quello che vuoi sapere:

La direttiva specifica la zona (zona) e il numero massimo possibile di richieste (raffica). Se la velocità supera le richieste indicate nella zona, la richiesta viene ritardata, in modo che le query vengano elaborate a una determinata velocità

Da quanto ho capito, le richieste oltre il burst saranno ritardate (impiega più tempo e attendi fino a quando non possono essere servite), con le nodelayopzioni il ritardo non viene utilizzato e le richieste in eccesso vengono negate con un errore 503.

Questo post sul blog ( archive.org ) fornisce una buona spiegazione di come funziona la limitazione della velocità su nginx:

Se sei come me, probabilmente ti starai chiedendo cosa significhi davvero scoppiare. Ecco il trucco: sostituisci la parola "burst" con "bucket" e supponi che a ogni utente venga assegnato un bucket con 5 token. Ogni volta che superano il tasso di 1 richiesta al secondo, devono pagare un token. Dopo aver speso tutti i loro token, viene visualizzato un messaggio di errore HTTP 503, che è diventato essenzialmente lo standard per "arretrare, amico!".


4
Penso che tu sia errato, il manuale di nginx afferma: "Le richieste eccessive vengono ritardate fino a quando il loro numero supera la dimensione massima di burst". Si noti che fino a quando non si supera il limite massimo il burst ha un significato completamente diverso rispetto al burst che hai detto. Hai anche confuso scoppiare con richieste in eccesso , credo che richieste in eccesso significhino che è al di sopra della zona, mentre potrebbe essere ancora al di sotto del massimo scoppio .
Hendy Irawan,

10

TL; DR: l'opzione di nodelay è utile se si desidera imporre un limite di velocità senza limitare la spaziatura consentita tra le richieste.

Ho avuto difficoltà a digerire le altre risposte, e poi ho scoperto una nuova documentazione di Nginx con esempi che rispondono a questo: https://www.nginx.com/blog/rate-limiting-nginx/

Ecco la parte pertinente. Dato:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

location /login/ {
  limit_req zone=mylimit burst=20;
  ...
}

Il parametro burst definisce quante richieste un client può fare in eccesso rispetto alla velocità specificata dalla zona (con la nostra zona mylimit di esempio, il limite di velocità è di 10 richieste al secondo o 1 ogni 100 millisecondi). Una richiesta che arriva prima di 100 millisecondi dopo che la precedente è stata inserita in una coda, e qui stiamo impostando la dimensione della coda su 20.

Ciò significa che se 21 richieste arrivano contemporaneamente da un determinato indirizzo IP, NGINX inoltra immediatamente il primo al gruppo di server upstream e inserisce i restanti 20 in coda. Inoltra quindi una richiesta in coda ogni 100 millisecondi e restituisce 503 al client solo se una richiesta in arrivo fa superare il numero di richieste in coda 20.

Se aggiungi nodelay:

location /login/ {
  limit_req zone=mylimit burst=20 nodelay;
  ...
}

Con il parametro nodelay, NGINX alloca ancora gli slot nella coda in base al parametro burst e impone il limite di velocità configurato, ma non distanziando l'inoltro delle richieste in coda. Invece, quando una richiesta arriva "troppo presto", NGINX la inoltra immediatamente fintanto che è disponibile uno slot nella coda. Contrassegna lo slot come "preso" e non lo libera per l'uso da parte di un'altra richiesta fino a quando non è trascorso il tempo appropriato (nel nostro esempio, dopo 100 millisecondi).


6

Il modo in cui lo vedo è il seguente:

  1. Le richieste verranno soddisfatte il più rapidamente possibile fino al superamento della tariffa di zona. La tariffa della zona è "in media", quindi se la tua tariffa è 1r/sed è veloce 10puoi avere 10 richieste in una finestra di 10 secondi.

  2. Dopo il superamento della tariffa di zona:

    un. Senza nodelay, ulteriori richieste fino a burstsaranno ritardate.

    b. Con nodelay, ulteriori richieste fino a burstsaranno servite il più rapidamente possibile.

  3. Dopo il burstsuperamento, il server restituirà la risposta di errore fino alla scadenza della finestra di burst. ad es. per velocità 1r/se raffica 10, il cliente dovrà attendere fino a 10 secondi per la successiva richiesta accettata.


3

L'impostazione definisce se le richieste verranno ritardate in modo che siano conformi alla velocità desiderata o se verranno semplicemente rifiutate ... in qualche modo se la limitazione della velocità è gestita dal server o la responsabilità viene passata al client.

nodelay presente

Le richieste saranno gestite il più rapidamente possibile; eventuali richieste inviate oltre il limite specificato verranno rifiutate con il codice impostato comelimit_req_status

nodelay assente (aka ritardato)

Le richieste verranno gestite a una velocità conforme al limite specificato. Ad esempio, se una velocità è impostata su 10 req / s, ciascuna richiesta verrà gestita in> = .1 (1 / velocità) secondi, non consentendo in tal modo il superamento della velocità, ma consentendo il backup delle richieste. Se un numero sufficiente di richieste esegue il backup per overflow del bucket (che sarebbe anche impedito da un limite di connessione simultanea), vengono respinte con il codice impostato come limit_req_status.

I dettagli cruenti sono qui: https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_limit_req_module.c#L263 in cui la logica entra in azione quando il limite non è stato ancora superato e ora il ritardo verrà eventualmente applicato alla richiesta. L'applicazione nodelayin particolare della direttiva entra in gioco qui: https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_limit_req_module.c#L495 facendo sì che il valore di delaysopra sia 0 innescando che gestore per restituire immediatamente NGX_DECLINEDquale passa la richiesta al gestore successivo (anziché NGX_AGAINquale verrà effettivamente rielaborata per essere elaborata di nuovo).


1

Non l'ho capito per la prima volta quando stavo leggendo l'introduzione da https://www.nginx.com/blog/rate-limiting-nginx/ .

Ora sono sicuro di aver capito e la mia risposta è finora la migliore. :)

Supponiamo che 10r/ssia impostato, la capacità massima del server è ad es. 10000r/sQual è 10r/mse al momento esiste solo 1 client.

Quindi ecco la differenza principale tra 10r/s per IP burst=40 nodelaye 10r/s per IP burst=40.

inserisci qui la descrizione dell'immagine

Come documentato da https://www.nginx.com/blog/rate-limiting-nginx/ ( consiglio vivamente di leggere prima l'articolo (tranne la sezione Limitazione della frequenza in due fasi )), questo comportamento risolve un problema. Quale?:

Nel nostro esempio, il 20 ° pacchetto nella coda attende 2 secondi per essere inoltrato, a quel punto una risposta potrebbe non essere più utile al client.

Controlla la bozza che ho fatto, la 40thrichiesta riceve risposta 1smentre l'altra 40thriceve risposta a 4s.

Ciò può sfruttare al meglio le capacità del server: rispedisce le risposte il più rapidamente possibile mantenendo comunque il x r/svincolo per un determinato client / IP.

Ma c'è anche un costo qui. Il costo sarà:

Se si dispone di molti clienti in coda sul client per esempio il server ha lasciati A, Be C.

Senza nodelay, le richieste vengono soddisfatte in un ordine simile a ABCABCABC.
Con nodelay, l'ordine è più probabile che sia AAABBBCCC.


Vorrei riassumere l'articolo https://www.nginx.com/blog/rate-limiting-nginx/ qui.

Soprattutto, la configurazione più importante è x r/s.

  1. x r/s solo, le richieste in eccesso vengono immediatamente respinte.

  2. x r/s+ burst, le richieste in eccesso vengono messe in coda.

1.vs 2., il costo è che sul lato client, le richieste in coda aumentano le possibilità di richieste successive che avranno avuto la possibilità di essere servite.

Ad esempio, 10r/s burst=20vs 10r/s, la 11thrichiesta dovrebbe essere rifiutata immediatamente in quest'ultima condizione, ma ora è in coda e verrà servita. La 11thrichiesta prende la 21thpossibilità della richiesta.

  1. x r/s+ burst+ nodelay, già spiegato.

PS La sezione di limitazione della frequenza in due fasi dell'articolo è molto confusa. Non capisco ma non sembra importare.

Per esempio:

Con questa configurazione in atto, un client che effettua un flusso continuo di richieste a 8 r / s sperimenta il seguente comportamento.

8 r / s? sul serio? Ci sono 17 richieste entro 3 secondi mostrati nell'immagine, 17/3 = 8?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.