Recentemente, assumi a manutenção de um Inicialização do Spring projeto. Esse projeto tem algumas RateLimit erros nos logs quando o aplicativo estava entrando em contato com uma API REST remota. Acontece que esse aplicativo também estava usando a API síncrona e bloqueadora RestTemplate para fazer as chamadas de API, em vez do mais recente Spring Cliente Webque, por acaso, está usando a API do Reactor por trás do capô.

E você sabe o que é ótimo no Reactor e no uso de APIs reativas em geral? Ele facilita muito a programação com fluxo de dados. O que também significa que facilita a implementação de estratégias de repetição.

Vamos falar primeiro sobre o erro no registro. O que recebi foi o seguinte:

Como de costume, a parte interessante dos rastreamentos de pilha está na parte superior. O erro é 429 Solicitações em excessoe a mensagem diz que há um Limite de taxa de 1 minuto. Decompondo isso, o status HTTP O código retornado é 429. É um erro de limite de taxa, o que significa que a API informa ao chamador que enviou um número excessivo de solicitações. Normalmente, isso pode ser resolvido esperando um pouco, e você pode até ter um Tentar novamente depois na resposta informando quanto tempo você precisa esperar.

Vamos ver como podemos obter essas informações com o WebClient do Spring:

Esse código está enviando um OBTER solicitação. O WebClient nos permite dar uma olhada na resposta da solicitação e reagir adequadamente graças à função onStatus method. O primeiro parâmetro é um booleano usado para filtrar o código de status HTTP retornado. Aqui, quando o código de status é 429, fazemos alguma coisa.

Vamos dar uma olhada no Resposta veja se há um cabeçalho Tentar novamente depois se for o caso, inicializamos o cabeçalho delayInSeconds com ela; caso contrário, definimos um valor padrão de 60. Em seguida, podemos enviar de volta o Resposta mapeado para um corpo RateLimitException. O conteúdo do corpo será usado como uma mensagem de erro e o delayInSeconds estará disponível em um campo separado. Dê uma olhada no código da Exceção para obter mais detalhes:

Portanto, o que precisa ser feito é capturar esse erro específico e tentar novamente após o período determinado. O Reactor facilita isso fornecendo Novas tentativas estratégias. Tudo o que você precisa fazer é chamar o retryWhen método:

Existem diferentes Repetir aqui podemos usar os métodos withThrowable() construtor. Ele fornece um Flux que deve conter o RateLimitException. Portanto, começamos aplicando um filtro para nos certificarmos disso. Em seguida, mapeamos essa exceção para o objeto Retry real. Aqui é o objeto Retry.fixedDelay tomando como parâmetros as tentativas máximas e a duração. A duração vem do RateLimitException que foi lançado anteriormente.

Com isso, toda vez que uma solicitação retornar um 429, o cliente aguardará o tempo apropriado até tentar novamente. E foi muito mais fácil implementar com o Reactor do que usar o try/catch com o RestTemplate. Sei que a programação reativa pode ser um pouco intimidadora no início, mas é uma ótima maneira de gerenciar fluxos de dados, como solicitações e respostas HTTP, ou de gerenciar conexões com bancos de dados que suportam programação reativa, como Couchbase.

Deseja mais ajuda e ideias?

Autor

Postado por Laurent Doguin

Laurent é um nerd metaleiro que mora em Paris. Em sua maior parte, ele escreve código em Java e texto estruturado em AsciiDoc, e frequentemente fala sobre dados, programação reativa e outras coisas que estão na moda. Ele também foi Developer Advocate do Clever Cloud e do Nuxeo, onde dedicou seu tempo e experiência para ajudar essas comunidades a crescerem e se fortalecerem. Atualmente, ele dirige as Relações com Desenvolvedores na Couchbase.

Deixar uma resposta