Estou recebendo a mensagem “429 Too Many Requests” para solicitações de API à minha instância auto-hospedada, mesmo com:
DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE aumentado para 600
Defini isso na seção env de app.yml e depois executei ./launcher rebuild e confirmei que a variável foi definida no contêiner reconstruído.
Isso é muito mais do que o número de solicitações por minuto que estou tentando.
uma chave de API de administrador irrestrita.
Parece que isso já foi discutido antes sem uma resposta clara sobre por que a alteração de DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE não parece funcionar:
Estou analisando isso novamente, pois lançamos uma integração do Discourse e queremos ter certeza de que não encontraremos nenhum problema relacionado à limitação de taxa.
Eu testei com uma nova chave para garantir que ela não seja limitada de forma alguma. Para ser claro, o que exatamente você quer dizer com uma chave de API de administrador?
Diz: “A chave de API não tem restrição e todos os endpoints são acessíveis.”
Estou testando isso fazendo requisições de API de um shell Python local, então elas vêm do mesmo endereço IP. Também encontramos os limites de taxa ao executar um script em nosso servidor. Nesse caso, todas as requisições vieram do mesmo endereço IP.
Confirmei que o limite de taxa é atingido com o seguinte código:
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
# Apenas obtenha uma fatia de 15 dos tópicos em topic_ids para teste.
topics = asyncio.run(get_topic_post_streams(topic_ids[:15]))
Note que o parâmetro max_per_second está comentado, o que resulta em nenhum limite no número de requisições.
Isso é concluído em 2,05 s e 2 das 15 requisições retornam 429.
Quando eu o executo com max_per_second=1, tudo é concluído com sucesso.
Me avise se posso fornecer mais detalhes. Obrigado!
Parece que eu não deveria estar recebendo esses 429s, independentemente de quaisquer configurações mencionadas nesse post. No exemplo que forneci, enviei 15 requisições, o que está abaixo de todos os limites padrão da API. Fiz isso usando uma chave de API e nome de usuário de administrador.
O exemplo não excede os seguintes padrões por IP:
Nem mesmo excede os limites não administrativos:
Alterar DISCOURSE_MAX_REQS_PER_IP_MODE para warn ou none não ajudou.
Estou perdendo alguma coisa?
Aliás, alterei as configurações editando app.yml e executando ./launcher destroy app && ./launcher start app.
Consigo ver em /var/log/nginx/access.log que o endereço IP está correto, então não acho que o Discourse considere todas as requisições vindas do mesmo IP.
Também consigo ver os endereços IP dos usuários no admin.
EDIT: Acabei de verificar o conteúdo da resposta de uma das requisições falhadas e notei que mencionava 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
Vou investigar mais sobre os tópicos que mencionam nginx.
location @discourse {
add_header Strict-Transport-Security 'max-age=31536000'; # lembre-se do certificado por um ano e conecte-se automaticamente ao HTTPS para este domínio
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;
}
}
Minhas perguntas restantes agora são:
Devo editar ambas as seções para corresponder às minhas configurações do Discourse? Ou apenas os valores para location @discourse?
Qual é a maneira correta de modificar esses valores e persistir as alterações em reconstruções?
Eu assumo que posso editar a configuração do nginx diretamente no contêiner e, em seguida, parar/iniciar o contêiner. Mas parece que esses valores vieram originalmente de templates/web.ratelimited.template.yml e podem ser substituídos em uma reconstrução?
Oof, agora estamos saindo da minha zona de conforto, receio.
Se você está sendo limitado pela taxa do nginx, então sim, mexer nessas configurações e torná-las menos restritivas faz sentido. Não tenho certeza se o Nginx pode adicionar endereços IP a uma lista de permissões?
Sim, você deve fazer algumas substituições com pups durante a compilação para tornar isso persistente, veja, por exemplo, web.ssl.template.yml sobre como abordar isso.
Ou você pode esquecer isso e fazer seu script cliente de API rodar mais devagar inserindo alguns sleeps em locais estratégicos. ← abordagem recomendada