Ricevo il messaggio “429 Too Many Requests” per le richieste API alla mia istanza self-hosted anche con:
DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE aumentato a 600
L’ho impostato nella sezione env di app.yml e poi ho eseguito ./launcher rebuild e ho confermato che la variabile era impostata nel container ricostruito.
questo è ben al di sopra del numero di richieste al minuto che sto tentando
una chiave API admin senza restrizioni
Sembra che questo sia stato discusso in precedenza senza una risposta chiara sul perché la modifica di DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE non sembri funzionare:
Ora sto esaminando nuovamente questo problema poiché abbiamo lanciato un’integrazione Discourse e vogliamo assicurarci di non incontrare problemi relativi ai limiti di frequenza.
L’ho testata con una nuova chiave per assicurarmi che non fosse limitata in alcun modo. Per essere chiari, cosa intendi esattamente con chiave API admin?
Ho creato una chiave con le seguenti impostazioni:
Dice: “La chiave API non ha restrizioni e tutti gli endpoint sono accessibili.”
Sto testando questo effettuando richieste API da una shell Python locale, quindi provengono dallo stesso indirizzo IP. Abbiamo anche riscontrato i limiti di frequenza durante l’esecuzione di uno script sul nostro server. In quel caso, tutte le richieste provenivano dallo stesso indirizzo IP.
Ho confermato che il limite di frequenza viene raggiunto con il seguente codice:
async def get_topic_post_stream(topic_id):
url = f"{DISCOURSE_URL}/t/{topic_id}"
async with httpx.AsyncClient(headers=HEADERS) as client:
topic = await client.get(url)
return topic.status_code
async def get_topic_post_streams(topic_ids):
tasks = [functools.partial(get_topic_post_stream, topic_id) for topic_id in topic_ids]
topics = await aiometer.run_all(
tasks,
# max_per_second=1,
)
return topics
# Ottieni solo una porzione di 15 degli argomenti in topic_ids per il test.
topics = asyncio.run(get_topic_post_streams(topic_ids[:15]))
Nota che il parametro max_per_second è commentato, il che non impone limiti al numero di richieste.
Questo viene completato in 2,05 secondi e 2 delle 15 richieste restituiscono 429.
Quando lo eseguo con max_per_second=1, tutto viene completato con successo.
Fammi sapere se posso fornire ulteriori dettagli. Grazie!
Mi sembra di non dover ricevere questi 429 indipendentemente da qualsiasi impostazione menzionata in quel post. Nell’esempio che ho fornito, ho inviato 15 richieste che rientrano in tutti i limiti predefiniti dell’API. L’ho fatto usando una chiave API e un nome utente amministratore.
L’esempio non supera i seguenti valori predefiniti per IP:
Non supera nemmeno i limiti per i non amministratori:
La modifica di DISCOURSE_MAX_REQS_PER_IP_MODE in warn o none non ha aiutato.
Mi sfugge qualcosa?
A proposito, ho modificato le impostazioni modificando app.yml ed eseguendo ./launcher destroy app && ./launcher start app.
Posso vedere in /var/log/nginx/access.log che l’indirizzo IP è corretto, quindi non credo che Discourse consideri tutte le richieste provenienti dallo stesso IP.
Posso anche vedere gli indirizzi IP degli utenti nell’area admin.
EDIT: Ho appena controllato il contenuto della risposta di una delle richieste fallite e ho notato che menzionava nginx:
<html>\r\n<head><title>429 Too Many Requests</title></head>\r\n<body>\r\n<center><h1>429 Too Many Requests</h1></center>\r\n<hr>\n<center>nginx</center>\r\n</body>\r\n</html>\r\n
Farò ulteriori indagini sugli argomenti che menzionano nginx.
location @discourse {
add_header Strict-Transport-Security 'max-age=31536000'; # ricorda il certificato per un anno e connettiti automaticamente a HTTPS per questo dominio
limit_conn connperip 20;
limit_req zone=flood burst=12 nodelay;
limit_req zone=bot burst=100 nodelay;
proxy_set_header Host $http_host;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_pass http://discourse;
}
}
Le mie restanti domande sono:
Dovrei modificare entrambe le sezioni per farle corrispondere alle mie impostazioni di Discourse? O solo i valori per location @discourse?
Qual è il modo corretto per modificare questi valori e mantenere le modifiche dopo le ricostruzioni?
Presumo di poter modificare direttamente la configurazione di nginx nel container e poi fermare/avviare il container. Ma sembra che questi valori provengano originariamente da templates/web.ratelimited.template.yml e possano essere sovrascritti durante una ricostruzione?
Mi dispiace, ora stiamo uscendo dalla mia zona di comfort.
Se sei limitato dalla frequenza di nginx, allora sì, armeggiare con quelle impostazioni e renderle meno restrittive ha senso. Non sono sicuro se Nginx possa creare una whitelist di indirizzi IP?
Sì, dovresti fare alcune sostituzioni con i pups durante la build per rendere questo persistente, vedi ad esempio web.ssl.template.yml su come procedere.
Oppure potresti dimenticarti di questo e far eseguire al tuo script client API più lentamente inserendo alcuni sleep in punti strategici. ← approccio consigliato